Repository navigation
JSON API reference
Voltron clients communicate with the back end by means of a JSON API which is exposed over a UNIX domain socket (~/.voltron/voltron.sock), and optionally a TCP socket and HTTP server. All of these methods expose the same API.
All API messages are valid JSON objects containing at least a type field, which specifies whether the message is a request or response message.
Messages may contain an optional data field, which is a hash containing message-specific data.
{
"type": "<message_type>",
...
"data": {
"<message_specific_field>": "some data"
}
}
A request contains at least a type field (which is always "request") and a request field that defines the type of request.
For example, a state request to get the current state of a debugger target:
{
"type": "request",
"request": "state"
}
Requests may also contain a data section which is used to pass request-specific parameters to the back end. For example, many request types accept a target_id field in the data section to specify a debugger target ("inferior" in GDB parlance).
For example, a registers request with a target_id field:
{
"type": "request",
"request": "registers",
"data": {
"target_id":0
}
}
Responses always have a data section, which either contains the result of the request, or an error code and message.
For example, the response to a targets request with an array containing the info for one target:
{
"type": "response",
"status": "success",
"data": {
"targets": [
{
"id": 0,
"file": "/bin/ls",
"arch": "x86_64"
}
]
}
}
An error response:
{
"type": "response",
"status": "error",
"data": {
"code": 0x1000,
"message": "An error occurred"
}
}
The following requests are defined in the core API:
- Version
- Wait
- State
- Targets
- Registers
- Memory
- Stack
- Disassemble
- Command
- Backtrace
- Breakpoints
- Connect FD
All requests (except wait) can return a busy error if the debugger is busy and unable to respond.
Get the API and debugger host version.
{
"type": "request",
"request": "version"
}
{
"type": "response",
"status": "success",
"data": {
"api_version": 1.0,
"host_version": "lldb-something"
}
}
Block until one of the requested state changes occurs or the timeout is up, in which case it will return an error.
{
"type": "request",
"request": "wait",
"data" {
"state_changes": [
"stopped"
],
"timeout": 10
}
}
state_changes - an array of state changes to wait for. Currently only "stopped" is supported. Optional. Default is ["stopped"].
timeout - timeout value after which the server will return an error response. Optional. Default is block indefinitely.
{
"type": "response",
"status": "success",
"data": {
"state": "stopped"
}
}
{
"type": "response",
"status": "error",
"data": {
"message": "The request timed out",
"code": 4100
},
}
Get a the state of a debugger target.
{
"type": "request",
"request": "state",
"data": {
"target_id": 0
}
}
{
"type": "response",
"status": "success",
"data": {
"state": "stopped"
}
}
Get a list of the debugger's targets.
{
"type": "request",
"request": "targets"
}
{
"type": "response",
"status": "success",
"data": {
"targets": [
{
"id": 0,
"file": "/bin/ls",
"arch": "x86_64"
}
]
}
}
Get the values of the CPU registers for a given target and thread.
{
"type": "request",
"request": "registers",
"data": {
"target_id": 0,
"thread_id": 1234
}
}
target_id - the target ID from which to read register values. Optional. Default is the first target.
thread_id - the thread ID from which to read register values. Optional. Default is the current thread.
{
"type": "response",
"status": "success",
"data": {
"registers": {
"rip": 0xffffff8012341234,
"rax": 0x4141414141414141,
...
}
}
}
Read memory from the inferior.
{
"type": "request",
"request": "read_memory",
"data": {
"target_id": 0,
"address": 0xffffff8012341234,
"bytes": 1024,
}
}
target_id - the target ID from which to read memory. Optional. Default is the first target.
bytes - the number of bytes to read. Required.
address - the address at which to start reading.
register - the register which contains the address at which to start reading.
Either address or register must be specified.
{
"type": "response",
"status": "success",
"data": {
"memory": "\x41\x41\x41\x41...",
"bytes": 1024
}
}
XXX: This isn't implemented yet, probably do it
{
"type": "response",
"status": "error",
"data": {
"code": 666,
"message": "Read failed at 0xffffff8012341266, only 50 bytes read",
"bytes": 50,
"memory": "\x41\x41\x41\x41..."
}
}
Read memory starting from the value contained in the inferior's stack pointer register.
{
"type": "request",
"request": "stack",
"data": {
"target_id": 0,
"bytes": 512
}
}
target_id - the target ID from which to read stack memory. Optional. Default is the first target.
bytes - the number of bytes to read. Required.
See Memory.
Disassemble instructions from the inferior's memory.
{
"type": "request",
"request": "disassemble",
"data": {
"target_id": 0,
"address": 0xffffff8012341234,
"count": 16
}
}
target_id - the target ID. Optional.
address - the address at which to start disassembling. Optional.
count - the number of instructions to disassemble. Required.
{
"type": "response",
"status": "success",
"data": {
"output": "mov blah blah",
"bytes": 1024
}
}
Execute a command in the debugger host and return the output.
{
"type": "request",
"request": "execute_command",
"data": {
"command": "x/32x $rsp"
}
}
command - the command to execute.
{
"type": "response",
"status": "success",
"data": {
"output": "0x12341234 0x12341234..."
}
}
Get a list of the current stack of function calls in a given thread.
XXX: Not implemented yet
{
"type": "request",
"request": "backtrace",
"data": {
"target_id": 0,
"thread_id": 1234
}
}
{
"type": "response",
"status": "success",
"data": {
"frames": [
etc
]
}
}
Get a list of the breakpoints set in an inferior.
XXX: Not implemented yet
{
"type": "request",
"request": "breakpoints",
"data": {
"target_id": 0
}
}
{
"type": "response",
"status": "success",
"data": {
"breakpoints": [
{"address": 0xffffff8012341234, "enabled": true}
]
}
}
This is a special request that connects this client session directly to a file descriptor belonging to the inferior.
Once the response has been sent the socket will be connected to the file descriptor. Once a session is connected to an fd, it cannot be disconnected without closing the socket.
If the request fails, an error response will be sent to the client.
XXX: Not implemented yet
{
"type": "request",
"request": "connect_fd",
"data": {
"fd": 0
}
}
{
"type": "response",
"status": "success"
}
XXX: List all the error types here