[About] [News] [Documentation] [Screenshots]

Appendix A. Bugle debugger protocol

A.1. Introduction

The debugger component of bugle uses a wire protocol to communicate data between the debugger filter-set and the debugger application. The protocol is documented here.

It should be noted that this protocol has many shortcomings:

  • It is unversioned, so the endpoints may be using different versions of the protocol and not be aware of this until something goes catastrophically wrong.

  • It is not endian-safe. The control codes are sent in big-endian, but the data being transferred is sent in the host encoding.

  • It may in places be dependent on the pointer size of the system, in particular when transferring GL pointer state.

  • Packets do not contain a length field, making it impossible to skip unknown packets.

In spite of these limitations, it has been successively used to debug an OpenGL ES application running on an ARM CPU with the debugger running on top of OpenGL on a 64-bit Intel CPU.

The goal is to eventually address these limitations, and patches are welcomed.

A.2. Basics

The protocol is a binary packet-based protocol. The debugger makes requests to the filter-set, which returns responses. Packets have identifiers to facilitate pipelining. In addition, there are certain responses that may be generated asynchronously by the filter-set.

A.2.1. Types

NameDescription
UINT3232-bit big-endian unsigned integer
INT3232-bit twos-complement big-endian signed integer
UINT6464-bit big-endian unsigned integer
INT6464-bit twos-complement big-endian signed integer
CODEsame as UINT32, but for debugger protocol enumerated values
GLENUMsame as UINT32, but for OpenGL enumerated values
BOOLA UINT32 with the value 1 (true) or 0 (false)
STRINGA length (as UINT32) followed by that number of bytes. The character set is UTF-8, in most cases it will be plain ASCII.
BLOBA piece of binary data, encoded in the same way as STRING

A.2.2. States

Over the lifetime of the debugged process, it will move between three states. When it first starts, it is in the startup state, and waits for instructions from the debugger. At this point, the debugger will send breakpoints and other requests that need to be in place before the program starts issuing GL commands. Once the REQ_RUN request is received, the program enters the running state. From this point, it will alternate between running and stopped. The filter-set will accept commands in both states (although if no GL commands are issued, the filter will not run and so will not be responsive). However, in the stopped state, the filter-set will block and wait for commands and will prevent the thread it is in from running, while in the running state, it will only process commands that are available[1] and will allow its thread to continue running normally.

A.3. Requests

These are the requests that the debugger may make to the filter-set. The values for CODE fields are listed symbolically; the symbol values can be found in common/protocol.h.

Each request starts with the request type and a request ID. Request IDs are arbitrary values chosen by the debugger to identify requests. Responses include the request ID, to facilitate matching of responses to requests. Request IDs need not be unique.

A.3.1. Run

Starts the program running. Once it is running, the response RESP_RUNNING is returned, ahead of any asynchronous response that might result.

TypeDescription
CODEREQ_RUN
UINT32request ID
UINT64process ID

A.3.2. Continue

Continue running a stopped program.

TypeDescription
CODEREQ_CONT
UINT32request ID

A.3.3. Step

Continue running, but break on the next call.

TypeDescription
CODEREQ_STEP
UINT32request ID

A.3.4. Break on function

Set or clear a breakpoint on a function.

TypeDescription
CODEREQ_BREAK
UINT32request ID
STRINGname of the function
BOOLtrue to set, false to clear

A.3.5. Break on event

Set or clear a breakpoint on an event class.

TypeDescription
CODEREQ_BREAK_EVENT
UINT32Request ID
CODE

one of

  • REQ_EVENT_GL_ERROR: error from glGetError
  • REQ_EVENT_COMPILE_ERROR: failed shader compilation
  • REQ_EVENT_LINK_ERROR: failed shader link
BOOLtrue to set, false to clear

A.3.6. Break on error

This is an obsolete command, equivalent to REQ_BREAK_EVENT with an event type of REQ_EVENT_GL_ERROR.

TypeDescription
CODEREQ_BREAK_ERROR
UINT32request ID
BOOLtrue to set, false to clear

A.3.7. Stop

Requests a running program to stop at the next available point. It is ignored if the program is already stopped when the command is received.

TypeDescription
CODEREQ_ASYNC
UINT32request ID

A.3.8. Quit

Requests the program to terminate.

TypeDescription
CODEREQ_QUIT
UINT32request ID

A.3.9. Filter-set activation and deactivation

Filter-sets can be enabled or disabled on the fly by the debugger, similarly to the way they can be activated or deactivated using key sequences.

TypeDescription
CODEREQ_ACTIVATE_FILTERSET or REQ_DEACTIVATE_FILTERSET
UINT32request ID
STRINGname of the filter-set

A.3.10. State requests

Requests a readout of all the GL state.

TypeDescription
CODEREQ_STATE_TREE_RAW
UINT32request ID

State can also be requested in a text form, but this is deprecated:

TypeDescription
CODEREQ_STATE_TREE
UINT32request ID

A.3.11. Data requests

Request data from a GL object. This command has a common header, and a number of possible sub-types.

A.3.11.1. Texture data

TypeDescription
CODEREQ_DATA
UINT32request ID
CODEREQ_DATA_TEXTURE
UINT32GL name of the texture object
GLENUMtexture target
GLENUMtexture face (used only for cubemaps, otherwise ignored)
UINT32texture level
GLENUMformat parameter to glGetTexImage
GLENUMtype parameter to glGetTexImage

A.3.11.2. Framebuffer data

TypeDescription
CODEREQ_DATA
UINT32request ID
CODEREQ_DATA_FRAMEBUFFER
UINT32GL name of the framebuffer object (zero for the window-system framebuffer)
GLENUMread buffer
GLENUMformat parameter to glReadPixels
GLENUMtype parameter to glReadPixels

A.3.11.3. Shader source

TypeDescription
CODEREQ_DATA
UINT32request ID
CODEREQ_DATA_SHADER
UINT32GL name of the shader object (either GLSL or ARB shader)
GLENUMshader type (GLSL) or target (ARB shader)

A.3.11.4. Info log

This is used for shader or program info log of a GLSL shader. It is valid to query for ARB programs, but the info log is always empty.

TypeDescription
CODEREQ_DATA
UINT32request ID
CODEREQ_DATA_INFO_LOG
UINT32GL name of the shader or program object
GLENUMshader type, or GL_PROGRAM_OBJECT_ARB for GLSL programs (even in OpenGL ES, where is not a defined enum)

A.3.11.5. Buffer

This query returns the contents of a buffer (VBO).

TypeDescription
CODEREQ_DATA
UINT32request ID
CODEREQ_DATA_BUFFER
UINT32GL name of the shader or program object

A.4. Synchronous responses

Synchronous responses are replies to requests. Each synchronous response start with a response type and the request ID of the request it is in response to. Responses are always returned in the same order as the requests were received, but may potentially be intermixed with asynchronous responses.

A.4.1. Error

This is a general-purpose error response to any request which failed. The error code is currently unused and will always be zero. It is reserved for future use, where defined error codes may facilitate automatic interpretation of the error.

TypeDescription
CODERESP_ERROR
UINT32request ID
CODEerror code
STRINGhuman-readable error message

A.4.2. Answer

This is a general-purpose successful answer response. The meaning of the value field is determined by the corresponding request. Currently, no requests use this field and its value is undefined.

TypeDescription
CODERESP_ANS
UINT32request ID
UINT32value

A.4.3. Running

This is sent in response to REQ_RUN, to indicate that the debugger has successfully initialised.

TypeDescription
CODERESP_ERROR
UINT32request ID

A.4.4. Binary state dumps

The GL state is returned as a contiguous block of responses, with no intermediate asynchronous responses. Each node in the tree is encoded as a RESP_STATE_NODE_BEGIN_RAW (which contains information about the root of the tree, if any), then the children encoded recursively, then a RESP_STATE_NODE_END_RAW response to indicate the end of the children. The same request ID is used for the whole set of responses.

A.4.4.1. Begin response

TypeDescription
CODERESP_STATE_NODE_BEGIN_RAW
UINT32request ID
STRINGname of the state (empty for the root state)
UINT32numeric name of the state, which is state dependent (typically it is a GL name)
GLENUMenum name of the state, which is state dependent (typically it is a pname parameter to a GL query function)
STRINGthe mangled type name, as returned by budgie_type_name
INT32element count for an array, −1 for a non-array, and −2 if an error occurred in trying to retrieve the value
BLOBthe value of the state (currently using host object representation)

A.4.4.2. End response

TypeDescription
CODERESP_STATE_NODE_END_RAW
UINT32request ID

A.4.5. Textual state dumps

Textual state dumps work similarly to binary state dumps, except that the state is formatting into a human-readable string by the filter-set. It is recommended that clients do not attempt to parse these strings, and should instead use a binary state dump if they intend to inspect values.

A.4.5.1. Begin response

TypeDescription
CODERESP_STATE_NODE_BEGIN
UINT32request ID
STRINGname of the state (empty for the root state)
UINT32numeric name of the state, which is state dependent (typically it is a GL name)
GLENUMenum name of the state, which is state dependent (typically it is a pname parameter to a GL query function)
STRINGthe human-readable value of the state

A.4.5.2. End response

TypeDescription
CODERESP_STATE_NODE_END
UINT32request ID

A.4.6. Data responses

The response to data requests varies by the sub-type of the request. In each case, the data is returned as a binary blob, exactly as it was returned by the appropriate GL query function. The client pixel pack state is set to the default, except that GL_PIXEL_PACK_ALIGNMENT is set to 1.

A.4.6.1. Texture data response

TypeDescription
CODERESP_DATA
UINT32request ID
CODEREQ_DATA_TEXTURE
BLOBtexture data
UINT32width
UINT32height (1 for 1D textures)
UINT32depth (1 for 1D and 2D textures)

A.4.6.2. Framebuffer data response

TypeDescription
CODERESP_DATA
UINT32request ID
CODEREQ_DATA_FRAMEBUFFER
BLOBframebuffer data
UINT32width
UINT32height (1 for 1D textures)

A.4.6.3. Shader source response

TypeDescription
CODERESP_DATA
UINT32request ID
CODEREQ_DATA_SHADER
STRINGshader source

A.4.6.4. Info log response

TypeDescription
CODERESP_DATA
UINT32request ID
CODEREQ_DATA_INFO_LOG
STRINGinfo log

A.4.6.5. Info log response

TypeDescription
CODERESP_DATA
UINT32request ID
CODEREQ_DATA_BUFFER
BLOBbuffer data

A.5. Asynchronous responses

Asynchronous responses are generated when the program transitions from running state to stopped state. Except where otherwise noted, they can occur any time the program is running, potentially interleaved with synchronous responses.

Asynchronous responses include a request ID field, which contains the request ID of the last request that started the program running.

A.5.1. Break

This response is sent when the program is stopped just before executing a function call. This can be due to a user breakpoint on the function, or reaching the next function after a REQ_STEP or REQ_ASYNC.

TypeDescription
CODERESP_BREAK
UINT32request ID
STRINGdescription of the function call

A.5.2. Break on event

This response is used when the program is stopped just after executing a function call, as a result of something that occurred in the debugged application (such as a GL error).

TypeDescription
CODERESP_BREAK_EVENT
UINT32request ID
STRINGdescription of the function call
STRINGdescription of the event

A.6. Protocol definition

The previous sectiosn describe the individual request and response packets. Here we describe their relationship to each other and the transitions between states in the system.

The intention is that except where otherwise noted, illegal requests should result in an error being returned. However, this is not fully implemented and you should not depend on this.

The table below shows the valid states for each command, the resulting state on success (empty meaning no change), and the expected non-error, synchronous response.

RequestOld stateNew stateResponse
REQ_RUNstartuprunningRESP_RUNNING
REQ_CONTstoppedrunningnone
REQ_STEP
REQ_BREAKany RESP_ANS
REQ_BREAK_EVENT
REQ_BREAK_ERROR
REQ_STOPstopped, runningstoppednone
REQ_QUITstopped, runningdeadnone (process exits)
REQ_ACTIVATE_FILTERSETstopped, running RESP_ANS
REQ_DEACTIVATE_FILTERSET
REQ_STATE_TREE_RAWstopped, running sequence of RESP_STATE_NODE_BEGIN_RAW and RESP_STATE_NODE_END_RAW
REQ_STATE_TREEsequence of RESP_STATE_NODE_BEGIN and RESP_STATE_NODE_END
REQ_DATAstopped, running RESP_DATA (with matching subtype)


[1] Actually, as long as there is data available on the connection, it will consume a complete command. Thus, sending a partial command and stopping will cause a stoppage. This should probably be fixed.


Get BuGLe at SourceForge.net. Fast, secure and Free Open Source software downloads