Skip to content

Latest commit

 

History

History
304 lines (228 loc) · 9.9 KB

File metadata and controls

304 lines (228 loc) · 9.9 KB

Implementation Details

╭───────────────────────────────────────────╮
│Aliceserver                                │
│ ┌───────────────────────────────────────┐ │
│ │                Server                 │ │
│ ├───────────┬───┬──────────┬─┬──────────┤ │
│ │           │   │ Adapter  │ │ Adapter  │ │
│ │ Transport │   ├──────────┤ ├──────────┤ │
│ │           │   │ Debugger │ │ Proxy    │ │
╰─┴─────▲─────┴───┴────▲─────┴─┴────▲─────┴─╯
        │              │            │        
  ╔═════▼═════╗   ╔════▼═════╗ ╔════▼═════╗  
  ║ Debugger  ║   ║  Remote  ║ ║  Remote  ║  
  ║  Client   ║   ║ Process  ║ ║  Server  ║  
  ╚═══════════╝   ╚══════════╝ ╚══════════╝  

Aliceserver is implemented using an Object-Oriented Programming model.

The debugger server provides types and structures that the adapters and debuggers must interpret.

Transports

Transports handle the transport of data from and to clients.

The medium can include streams, sockets, anything really.

Each transport class inherits transport.ITransport.

Available transports:

  • StdioTransport: Implemented using standard streams.
  • SocketTransport: Implemented using Socket (for TCP and UNIX sockets).
  • NamedPipeTransport: Implemented using Windows NamedPipes.

StdioTransport

File: source/transports/stdio.d

StdioTransport uses the standard Phobos stream handles.

Nothing special. Uses poll.2 and PeekNamedPipe to perform peeking.

SocketTransport

File: source/transports/socket.d

SocketTransport uses Phobos Socket (std.socket) for TCP and UNIX socket transports.

Socket.select is used to know if the socket has data.

Path resolution is done by the server. When --pipe= argument starts with /, it is assumed a full path. Otherwise, XDG_RUNTIME_DIR is checked and used as prefix if it exists. If not, /tmp/ is used as prefix.

NamedPipeTransport

File: source/transports/pipe.d

NamedPipeTransport uses the Win32 API.

Duplex Named Pipes are created with PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS (byte-oriented, blocking, and refusing remote connections).

Uses PeekNamedPipe for peeking data.

Path resolution is done by the server. When --pipe= argument starts with \\, it is assumed a full path. Otherwise, \\.\pipe\ is prefixed.

Adapters

Adapters have the responsibility of handling the behavior of the given transport and the debugger instances.

Using the transport instance, adapters need to parse requests and send formatted replies and events back to the client via the transport instance.

Using the debugger instance, adapters need to interpret commands and handle debugger events.

After setting up instances, the server calls IAdapter.loop(ITransport, IDebugger).

Each adapter inherits adapter.IAdapter.

Available adapters:

  • DAPAdapter: Implements Debug Adapter Protocol as an adapter.
  • MIAdapter: Implements GDB's Machine Interface as an adapter.

Debuggers

Used to interface a debugger that manipulates processes.

Each debugger class inherits debugger.IDebugger.

Right now, only AlicedbgDebugger is available as a debugger.

Adapter Details

DAP

File: source/adapters/dap.d

Debugger Adapter Protocol (DAP) is a protocol using JSON-RPC that was introduced in vscode-debugadapter-node and was readapted as a standalone protocol for debugging various processes and runtimes in Visual Studio Code.

This chapter reuses terminology from DAP, such as Integer meaning, strictly speaking, a 32-bit integer number (int), and Number meaning a 64-bit double-precision floating-point number (IEEE 754 double).

Connection Details

DAP has two connection models: Single-session and multi-session.

  • Single-session: Using standard I/O (stdio), a single adapter instance is started.
  • Multi-session: Using TCP/IP, every new connection initiates a new debug session.

Messages are encoded as HTTP messages using the UTF-8 encoding and JSON payloads.

Currently, there is only one header field, Content-Length, that determines the length of the message (payload). This field is read as an Integer.

A typical request may look like this:

Content-Length: 82\r\n
\r\n
{"seq":1,"type":"request","command":"initialize","arguments":{"adapterId":"test"}}

And a typical response may look like this:

Content-Length: 81\r\n
\r\n
{"command":"initialize","request_seq":1,"seq":1,"success":true,"type":"response"}

Both client and server maintain their own sequence number, starting at 1.

NOTE: lldb-vscode starts their seq number at 0, while not as per specification, it poses no difference to its usage.

Supported Requests

Implementation-specific details:

  • launch request:
    • arguments:path: (Required) [String] File path.
  • attach request:
    • arguments:pid: (Required) [Integer] Process ID.

Command support:

Command Supported? Comments
attach ✔️ __restart argument not supported.
breakpointLocations
completions
configurationDone ✔️
continue ✔️
dataBreakpointInfo
disassemble
disconnect ✔️
evaluate
exceptionInfo
goto
gotoTargets
initialize ✔️ Locale is not supported.
launch ✔️ noDebug and __restart are not supported.
loadedSources
modules
next
pause
readMemory
restart
restartFrame
reverseContinue
scopes
setBreakpoints
setDataBreakpoints
setExceptionBreakpoints
setExpression
setFunctionBreakpoints
setInstructionBreakpoints
setVariable
source
stackTrace
stepBack
stepIn
stepInTargets
stepOut
terminate ✔️
terminateThreads
threads
variables
writeMemory

Supported Events

Event Supported? Comments
breakpoint
capabilities
continued
exited ✔️
initialized
invalidated
loadedSource
memory
module
output ⚠️
process
progressEnd
progressStart
progressUpdate
stopped ⚠️
terminated
thread

MI

File: source/adapters/mi.d

Machine Interface is a line-oriented protocol introduced in GDB 5.1.

Connection Details

In a typical setting, MI uses the standard streams to communicate with the child process.

Once the server starts running, it may already emit console streams, until (gdb)\n is printed, indicating that the server is ready to receive commands.

Commands are almost the same as you would use on GDB:

attach 12345\n

Replies to commands start with a ^ character:

^done\n

Or on error (note: \\n and \\" denote c-string formatting):

^error,msg="Example text.\\n\\nValue: \\"Test\\""\n

Events, console streams, logs, start with a significant unique character.

For example, command input (e.g., test\n) will be replied as &"test\\n"\n using c-string formatting.

Reply/Event Character Description
Result ^ Used to reply to a command, if successful or erroneous.
Exec * Async execution state changed.
Notify = Async notification related to the debugger.
Status + Async status change.
Console Stream ~ Console messages intended to be printed.
Target Stream @ Program output when truly asynchronous, for remote targets.
Log Stream & Internal debugger messages.

Some commands may start with -.

Supported Requests

NOTE: Command focus is on GDB, lldb-mi commands may work.

Request Commands Supported? Comments
Attach target-attach, attach ✔️
Launch -exec-run, run, target exec, -file-exec-and-symbols ✔️
Set arguments -exec-arguments ✔️
Continue -exec-continue, continue ✔️
Pause -exec-interrupt, pause ✔️
Terminate -exec-abort ✔️
Detach -target-detach, -gdb-detach, detach ✔️
Disconnect -target-disconnect ✔️
Set working directory -environment-cd ⚠️ Stub, not fully implemented
Thread info -thread-info ✔️
Show show ⚠️ Only show version supported
Command info -info-gdb-mi-command ✔️
List features -list-features ✔️
Settings -gdb-set, -inferior-tty-set ⚠️ Stubs required by clients
Quit -gdb-exit, quit, q ✔️

Supported Events

Request Details Supported? Comments
Continued ✔️
Exited Reasons: exited, exited-normally ✔️
Output
Stopped Reasons: breakpoint-hit, signal-received, end-stepping-range ✔️