Skip to content

V5 Debugger Server Protocol v2

All programming, documentation, and spec authoring was done by Hunter Stasonis

This program and its documentation have been placed under the MIT License, and is provided without warranty of any kind

Constants and Definitions

Throughout this document many words many be underlined with a dotted line, hovering over these words will show their definition.

Changes since v1

Version 2 of the debug server protocol introduces features for breakpoints, and setting variable memory along with adding subargument brackets around data field arguments in some message types.

Since message types which where introduced in a previous version of the protocol have been modified, version 2 should be considered not backwards-compatible.

If you wish to view the previous protocol documentation use the version switcher at the top of the screen.

Notes on literals

Some literals such as true and false are used on this page, their values should not be interpreted as their String names but instead their actual value. Hovering over literals will show their actual values.

Try it out!

What is the value of true? Hover over the next word: true

What is the value of false? Hover over the next word: false

Communication

v5dbg communicates over USB serial. The debug server opens the pseudofile provided by the PROS kernel located at /ser/sout in write mode, messages are serialized and written to this file using fwrite. COBS and stream multiplexing should be disabled for this file so data can be read raw by the debugger.

Messages

Messages are payloads of data sent from either the debugger, or debug server. All messages are formatted as follows, left to right.

  • Message begin
  • Protocol version
  • Message type
  • Message payload
  • Newline

An example message can be seen as %2:1:0, message type 1 is program suspend. It should be noted that if more than two message separator characters are used then any located after the third are ignored and are merged into the message payload.

If we have the message %2:2:0:1:2:3 then the message payload should be 0:1:2:3, the extra message separator characters do not mess up the parser state and does not throw a warning or error of any kind

Message Types

Message types are defined as enums within v5dbg/protocol.h (include directory), the DEBUGGER_MESSAGE_MAX is used as a basic check to determine if a message type is invalid.

Message IDs can be considered unsigned ints since they never can be negative, and a message should be assumed invalid or corrupted if so.

enum v5dbg_message_type_e
{
  /// @brief  Connection opened
  DEBUGGER_MESSAGE_OPEN = 0,

  /// @brief  Request program suspension, assume it has occurred when a DEBUG_MESSAGE_RSUSPEND is parsed
  DEBUGGER_MESSAGE_SUSPEND = 1,

  /// @brief  Connection closed
  DEBUGGER_MESSAGE_CLOSE = 2,

  /// @brief  Allocate a string, can be processed by the debugger however it likes
  DEBUGGER_MESSAGE_ALLOCATE_STRING = 3,

  /// @brief  Resume the program from a suspended state
  DEBUGGER_MESSAGE_RESUME = 4,

  /// @brief  Respond with DEBUGGER_MESSAGE_RTHREADS containing a comma separated list of every thread being managed by
  /// v5dbg
  DEBUGGER_MESSAGE_THREADS = 5,

  /// @brief  Return message for DEBUGGER_MESSAGE_THREADS
  DEBUGGER_MESSAGE_RTHREADS = 6,

  /// @brief  Get the vstack for the given thread index
  DEBUGGER_MESSAGE_VSTACK_FOR = 7,

  /// @brief  Return message for DEBUGGER_MESSAGE_VSTACK_FOR, keep accepting messages until DEBUGGER_MESSAGE_VSTACK_END
  DEBUGGER_MESSAGE_RVSTACK = 8,

  /// @brief  Stop accepting DEBUGGER_MESSAGE_RVSTACK messages
  DEBUGGER_MESSAGE_VSTACK_END = 9,

  /// @brief  List memory for the given stack frame with thread ID
  DEBUGGER_MESSAGE_LMEM_FOR = 10,

  /// @brief  Returned message for DEBUGGER_MESSAGE_LMEM_FOR, keep accepting messages until DEBUGGER_MESSAGE_LMEM_END
  DEBUGGER_MESSAGE_RLMEM = 11,

  /// @brief  Stop accepting DEBUGGER_MESSAGE_RLMEM messages
  DEBUGGER_MESSAGE_LMEM_END = 12,

   /// @brief  Sent to the debugger every time a breakpoint is activated and the program is suspended
   DEBUGGER_MESSAGE_BREAK_INVOKED = 13,

   /// @brief  List all breakpoints registered in the program
   DEBUGGER_MESSAGE_LBREAKPOINTS = 14,

   /// @brief  Sent for every breakpoint registered with the debug server
   DEBUGGER_MESSAGE_RBREAKPOINT = 15,

   /// @brief  Stop accepting DEBUGGER_MESSAGE_RBREAKPOINT messages
   DEBUGGER_MESSAGE_END_BREAKPOINTS = 16,

   /// @brief  Sent to the debug server in order to disable/enable a breakpoint by ID
   DEBUGGER_MESSAGE_BREAKPOINT_SET_STATUS = 17,

   /// @brief  Set the contents of the memory which is backing a variable
   DEBUGGER_MESSAGE_MEMORY_SET = 18,

   /// @brief  Used to return information and state of a memory set call
   DEBUGGER_MESSAGE_RMEMORY_SET = 19,

  /// @brief  Max debugger message ID
  DEBUGGER_MESSAGE_MAX = 20
};

Subarguments

Subarguments introduce a way for messages to include more complex data in their 3rd data field. Since the message parser only parses up to the 2nd message separator character the third data field can have message separators located in it.

The subargs parser allows for another array of elements to be placed into the data field, the simplest way to perform this would be to split the data field on the message separator character. If we want to include data inside the data field that has message separators(such as C++ typenames) we need an escape character.

The [ and ] character

When the first character of an element is an [ we ignore any message separator characters we come across until we encounter a ] character located before a message separator or a newline.

Without subarguments

Imagine we have this message:

%2:1:std::vector<int>:helloWorld

It's parameters are broken down into:

  • 1
  • 1
  • std::vector<int>:helloWorld

When we split the data parameter of the message by the message separator we get:

  • std
  • :vector<int>
  • helloWorld

This IS NOT what we want!

With subarguments

Taking our old string from the previous example and adding subargumrnts we get:

%2:1:[std::vector<int>]:helloWorld

It's parameters are broken down the same way during message parsing

Now instead of splitting on the message seperator the subargument parser is called creating:

  • std::vector<int>
  • helloWorld

This IS what we want!

References

You can find the official implementation (s) of a subargs parser below:

Variable set mode

The variable set mode dictates the behavior of the `DEBUGGER_MESSAGE_MEMORY_SET message.

Notice

Use the actual value of each enum and not its string name.

enum v5dbg_variable_set_mode_e
{
    /// @brief  Set the memory of this variable once
    VARIABLE_SET_MODE_SINGLE = 0,

    /// @brief  Set the memory of this variable even after its reallocated
    VARIABLE_SET_MODE_CONST = 1
};

Behaviors

Messages may be marked with icons, hovering over them will show information about the specific message type. Messages that do not state their argument type can be assumed to not use subarguments, or comma splitting.

If messages have more than one argument they will specify their argument type next to their enum name in the title.

DEBUGGER_MESSAGE_OPEN

Sent by the debug server to the debugger at program startup and every 2 seconds that the program is running. The debugger will only connect to the debug server if it can detect and read this message, the debugger will also print a hang message if it fails to receive an OPEN message atleast once every 5 seconds.

DEBUGGER_MESSAGE_ALLOCATE_STRING

When sent to the debug server this message sent unaltered back to the debugger, this was used for testing.

DEBUGGER_MESSAGE_SUSPEND

Requests the debug server to suspend all of it's supervised tasks, no response is sent to the client.

DEBUGGER_MESSAGE_RESUME

Requests the debug server to resume all of it's supervised tasks, no response is sent to the client.

DEBUGGER_MESSAGE_THREADS

Responds with a single DEBUGGER_MESSAGE_RTHREADS message containing all the debugger's supervised threads.

DEBUGGER_MESSAGE_RTHREADS

Response to a DEBUGGER_MESSAGE_THREADS message.

The following parameters repeat for every thread.

Parameter Docs
Index 0 String Name of the thread
Index 1 unsigned int ID of the thread
Example message

%2:6:Worker Thread,0,Odom Thread,1,OpControl,2

DEBUGGER_MESSAGE_VSTACK_FOR

When sent to the debug server it returns a series of DEBUGGER_MESSAGE_RVSTACK messages for each frame of the stack before ending with a DEBUGGER_MESSAGE_VSTACK_END message.

Parameter Docs
Index 0 unsigned int Thread ID to grab the callstack for

DEBUGGER_MESSAGE_RVSTACK

This message is sent repeatedly until a DEBUGGER_MESSAGE_VSTACK_END message is sent.

Parameter Docs
Index 0 unsigned int of the frame ID
Index 1 String Name of the function
Index 2 String File path to the function
Index 3 unsigned int Line number inside of the file where this function begins

DEBUGGER_MESSAGE_VSTACK_END

This message is sent to signal that the debugger can stop waiting for DEBUGGER_MESSAGE_RVSTACK messages.

The data field may be filled with any data the server wishes but it can be ignored.

DEBUGGER_MESSAGE_LMEM_FOR

This message is sent to the debug server to request a series of DEBUGGER_MESSAGE_RLMEM messages terminated by a DEBUGGER_MESSAGE_LMEM_END which contains captured local memory.

Parameter Docs
Index 0 unsigned int Frame ID
Index 1 unsigned int Thread ID

DEBUGGER_MESSAGE_RLMEM

This message is sent repeatedly until a DEBUGGER_MESSAGE_LMEM_END message is sent.

Parameter Docs
Index 0 String C++ typename of this variable
Index 1 String Name of this variable
Index 2 String Path to the file this variable is in
Index 3 unsigned int Line number this variable was exposed on
Index 4 String Pretty printed buffer for this variable

DEBUGGER_MESSAGE_LMEM_END

This message is sent to signal that the debugger can stop waiting for DEBUGGER_MESSAGE_RLMEM messages.

The data field may be filled with any data the server wishes but it can be ignored.

DEBUGGER_MESSAGE_BREAK_INVOKED

This message is sent from the debug server to the debugger when a breakpoint is tripped. By the time this message is parsed it can be assumed that the program is suspended and can be resumed with a call to DEBUGGER_MESSAGE_RESUME

Parameter Docs
Index 0 unsigned int ID of this breakpoint
Index 1 String Name of this breakpoint
Index 2 String Path to the file this breakpoint is in
Index 3 unsigned int Line number this breakpoint was placed on

DEBUGGER_MESSAGE_LBREAKPOINTS

Responds with a series of DEBUGGER_MESSAGE_RBREAKPOINT messages for each registered breakpoint.

Parameter Docs
Index 0 bool If set to true then "hidden" breakpoints are returned

DEBUGGER_MESSAGE_RBREAKPOINT

This message is sent repeatedly until a DEBUGGER_MESSAGE_END_BREAKPOINTS message is sent

Parameter Docs
Index 0 unsigned int Breakpoint ID
Index 1 String Function that breakpoint is in
Index 2 String Path to the file that the breakpoint is in
Index 3 unsigned int Line number which this breakpoint is on

DEBUGGER_MESSAGE_END_BREAKPOINTS

This message is sent to signal that the debugger can stop waiting for DEBUGGER_MESSAGE_RBREAKPOINT messages.

The data field may be filled with any data the server wishes but it can be ignored.

DEBUGGER_MESSAGE_BREAKPOINT_SET_STATUS

Request the debug server to change the status of a breakpoint, no response is sent to the client.

Parameter Docs
Index 0 unsigned int Breakpoint ID
Index 1 bool true to enable to breakpoint, false to disable

DEBUGGER_MESSAGE_MEMORY_SET

Request the debug server to set the value of a variable to the given value, a DEBUGGER_MESSAGE_RMEMORY_SET message is sent upon completion.

Parameter Docs
Index 0 String Name of the variable to set
Index 1 String Data to set the variable too, data is converted to the correct data type server-side
Index 2 unsigned int Stack frame where this variable is located
Index 3 unsigned int Thread ID where the stack frame is located
Index 4 v5dbg_variable_mode_e Variable set mode

DEBUGGER_MESSAGE_RMEMORY_SET

Sent after a DEBUGGER_MESSAGE_MEMORY_SET operation is completed.

The data field consists of a String value which corresponds to the completion status of the operation.

If the value in the data field is 0x0 (String literal) the debug server should attempt to clear the recopy buffer which was allocated on a constant copy set memory operation.

Result value Help
MemorySet Success message, the operation completed
AllocatorFailure Failed to allocate the copy buffer server-side
ConversionFailure Failed to convert the input buffer to the required data type
NoVariable No variable in the given scope exists with the provided name
ResetCopyBuffer The copy buffer used for constant sets was cleared