Difference between revisions of "Scalable Remote Debugger Protocol"

From Kodewerx
Jump to: navigation, search
m (Ideas: wiki syntax error)
(Ideas: Fixed table, general cleanup)
Line 33: Line 33:
 
So let's break these components down, hypothetically, and get into some details, ordered lowest layer first:
 
So let's break these components down, hypothetically, and get into some details, ordered lowest layer first:
  
# '''Physical layer''': Some examples of wires to support include LAN (Ethernet/WiFi), Wireless (bluetooth) RS-232 (serial COM port, USB COM port), Inter-Process Communication (Domain Sockets? DBUS?) ...
+
# '''Physical layer''': Some examples of wires to support include LAN (Ethernet/WiFi), Wireless (bluetooth) RS-232 (serial COM port, USB COM port), Inter-Process Communication (Domain Sockets? DBUS?)
# '''Transport layer''': Some examples of transport protocols include TCP/IP, UDP/IP (LAN, IPC via Domain Sockets, ...), UART (RS-232, ...), IPC-specific (DBUS, ...)
+
# '''Transport layer''': Some examples of transport protocols include TCP/IP, UDP/IP (LAN, Domain Sockets), UART (RS-232), IPC-specific (DBUS)
 
# '''Application layer''': A library (or similar service, E.G. a daemon) to tie all transport layers into a single API that, to the application, looks like one simple interface to connect and send/receive data. The library/daemon will have to handle the transport-specific details behind-the-scenes.
 
# '''Application layer''': A library (or similar service, E.G. a daemon) to tie all transport layers into a single API that, to the application, looks like one simple interface to connect and send/receive data. The library/daemon will have to handle the transport-specific details behind-the-scenes.
  
 
Thinking about this led to a conundrum; If we support multiple wires, we have to support multiple transport protocols which are compatible with those wires. And if we support multiple transport protocols, we have to know which one our target implements. To make the API as simple as possible, we must not force clients to choose from configurable options (for a bad example) that requires a large degree of changes for each different type of connection made. How do we simplify the API so that a user can just plain connect without doing any pre-setup work?
 
Thinking about this led to a conundrum; If we support multiple wires, we have to support multiple transport protocols which are compatible with those wires. And if we support multiple transport protocols, we have to know which one our target implements. To make the API as simple as possible, we must not force clients to choose from configurable options (for a bad example) that requires a large degree of changes for each different type of connection made. How do we simplify the API so that a user can just plain connect without doing any pre-setup work?
  
Answer: The [[http://en.wikipedia.org/wiki/URI_scheme URI scheme]]. The unfortunate downside to this solution is that it is undesired to use URI schemes without registering them with IANA. However, an argument could be made that these schemes would not be used for general network/internet communication. A few popular examples of a similarly non-networked schemes are the file: and about: URI schemes. (The exception here is that at least one physical layer (LAN) could be used for over-the-internet communication; but this has great benefits in its own right.)
+
Answer: The [http://en.wikipedia.org/wiki/URI_scheme URI scheme]. The unfortunate downside to this solution is that it is undesired to use URI schemes without registering them with IANA. However, an argument could be made that these schemes would not be used for general network/internet communication. A few popular examples of a similarly non-networked schemes are the file: and about: URI schemes. (The exception here is that at least one physical layer (LAN) could be used for over-the-internet communication; but this has great benefits in its own right.)
  
 
The following table represents some examples of how URI schemes could be used as debugger protocols:
 
The following table represents some examples of how URI schemes could be used as debugger protocols:
  
{|
+
{| style="border-collapse: collapse; width: 100%;"
| tcpd://192.168.1.20/ | TCP/IP to remote host 192.168.1.20 on a pre-defined default port
+
|-
| udpd://192.168.1.20:9424/ | UDP/IP to remote host 192.168.1.20 on port 9424
+
| style="border: 1px solid #000000;" | <nowiki>tcpd://192.168.1.20/</nowiki>
| uartd://localhost:3/ | UART COM port 3 on localhost
+
| style="border: 1px solid #000000;" | TCP/IP to remote host 192.168.1.20 on a pre-defined default port
| dbusd://localhost/ | DBUS IPC on localhost
+
|-
 +
| style="border: 1px solid #000000;" | <nowiki>udpd://192.168.1.20:9424/</nowiki>
 +
| style="border: 1px solid #000000;" | UDP/IP to remote host 192.168.1.20 on port 9424
 +
|-
 +
| style="border: 1px solid #000000;" | <nowiki>uartd://localhost:3/</nowiki>
 +
| style="border: 1px solid #000000;" | UART COM port 3 on localhost
 +
|-
 +
| style="border: 1px solid #000000;" | <nowiki>dbusd://localhost/</nowiki>
 +
| style="border: 1px solid #000000;" | DBUS IPC on localhost
 
|}
 
|}
  

Revision as of 08:09, 18 October 2008

This page is currently serving as a reference to kick-start development of the universal debugger protocol which will be used by the Universal Debugger Project and hopefully many, many other debuggers and debugger interfaces in the years to come.

References

These references are listed in order of relevance; most relevant first.

  1. RFC-909: Loader Debugger Protocol
  2. GDB Remote Serial Protocol
  3. RFC-643: Network Debugging Protocol
  4. IEN-158: XNET Debugging Protocol
  5. DBGp: A common debugger protocol for languages and debugger UI communication

The relevancy I've determined for this list is due to interest in these specs, as well as potential generic uses and protocol extension.

RFC-909 is so far the closest thing I have found which resembles the general idea I have for a "Universal Debugger Protocol". It's composed as a simple binary packet, it's extensible, and it's designed to be stacked on top of existing transport protocols such as TCP/IP. I doubt this exact spec will fit all of our needs, but it is certainly a good start.

GDB provides a fairly popular protocol. This one is designed for serial communications, so it will work well with small embedded devices. But it could be complicated to extend while retaining its GDB friendliness.

RFC-643 and IEN-158 are interesting only because they show that some experimentation on the ideas of remote debugging have been employed in the past. Unfortunately, these specs were designed for a specific architecture, and are of little practical use for our purposes.

DBGp shows what a modern remote debugging protocol can look like; including modern XML syntax. The downside to this is that low-level debuggers in small embedded devices are unlikely to parse XML at all.

Ideas

This section represents my (Parasyte) own personal opinions and ideas, and should not be taken as advocacy for standardization.

One of the main goals of developing a "universal" protocol for debugging is that it must be usable everywhere; in small embedded devices, and some of the most powerful machines in the world. This kind of flexibility must be designed around multiple layers of abstraction. See OSI Model and Internet Protocol Suite for examples of abstraction layers used in communications technologies.

At the lowest layer, you find the wire; the physical means of transmitting information over distance. For our purposes, we should not limit ourselves to a single wire. Instead, we should allow the use of multiple wires, user-selectable, but never more than one at a time.

The following layers get more and more generic and abstract, until you reach the highest layer which represents what the application sees and interacts with. This would be the "protocol" itself.

So let's break these components down, hypothetically, and get into some details, ordered lowest layer first:

  1. Physical layer: Some examples of wires to support include LAN (Ethernet/WiFi), Wireless (bluetooth) RS-232 (serial COM port, USB COM port), Inter-Process Communication (Domain Sockets? DBUS?)
  2. Transport layer: Some examples of transport protocols include TCP/IP, UDP/IP (LAN, Domain Sockets), UART (RS-232), IPC-specific (DBUS)
  3. Application layer: A library (or similar service, E.G. a daemon) to tie all transport layers into a single API that, to the application, looks like one simple interface to connect and send/receive data. The library/daemon will have to handle the transport-specific details behind-the-scenes.

Thinking about this led to a conundrum; If we support multiple wires, we have to support multiple transport protocols which are compatible with those wires. And if we support multiple transport protocols, we have to know which one our target implements. To make the API as simple as possible, we must not force clients to choose from configurable options (for a bad example) that requires a large degree of changes for each different type of connection made. How do we simplify the API so that a user can just plain connect without doing any pre-setup work?

Answer: The URI scheme. The unfortunate downside to this solution is that it is undesired to use URI schemes without registering them with IANA. However, an argument could be made that these schemes would not be used for general network/internet communication. A few popular examples of a similarly non-networked schemes are the file: and about: URI schemes. (The exception here is that at least one physical layer (LAN) could be used for over-the-internet communication; but this has great benefits in its own right.)

The following table represents some examples of how URI schemes could be used as debugger protocols:

tcpd://192.168.1.20/ TCP/IP to remote host 192.168.1.20 on a pre-defined default port
udpd://192.168.1.20:9424/ UDP/IP to remote host 192.168.1.20 on port 9424
uartd://localhost:3/ UART COM port 3 on localhost
dbusd://localhost/ DBUS IPC on localhost

The 'd' prefix on these examples is to specify 'debugger' protocols, but this strategy should not be used in any official standard specification. It is used here only to differentiate between (for example) plain old tcp:// which appears as if it means something entirely unrelated to debugging.

The latter two examples look a bit odd with localhost being the destination, but this is necessary, since the localhost is the destination for hosting the UART COM port and IPC interface. Using non-loopback interfaces (IP addresses outside of the local machine) with these protocols should be undefined, unless there is evidence that connecting to COM ports/IPC interfaces on other machines across a network is practical and plausible.

These URI schemes give a very simple and elegant solution to the concerns it addresses. No longer will you be stuck with complicated configuration settings like the example below (upper left group box) ... and this is not an incredibly complex configuration dialog, as it is; instead, connecting to ANY low-level debugger in the world will be as simple as typing a URL.

Gscc config.png