CodeQL / Analyze (actions) (push) Canceled after 0s
CodeQL / Analyze (python) (push) Canceled after 0s
pre-commit / pre-commit (push) Canceled after 0s
Multi-Arch CI / setup (push) Canceled after 0s
Publish build_manylinux_x86_64 images / publish_build_manylinux_x86_64 (push) Canceled after 0s
Setup (Multi-Arch) / setup (push) Canceled after 0s
Multi-Arch CI / Linux::${{ fromJSON(needs.setup.outputs.linux_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubi10 image / publish_no_rocm_image_ubi10 (push) Canceled after 0s
Multi-Arch CI / Windows::${{ fromJSON(needs.setup.outputs.windows_build_config || '{}').build_variant_label || 'skip' }} (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Multi-Arch CI / Manifest Diff (push) Canceled after 0s
TheRock Manifest Diff Report / Generate Manifest Diff Report (push) Canceled after 0s
Multi-Arch CI / CI Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_ocl_rt images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04_rocgdb images / publish_no_rocm_image_ubuntu24_04_rocgdb (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_ocl_rt (push) Canceled after 0s
Publish TheRock Docker image / build-and-push-image (push) Canceled after 0s
Unit Tests / Unit Tests :: ubuntu-24.04 (push) Canceled after 0s
Unit Tests / Unit Tests :: windows-2022 (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_media (push) Canceled after 0s
Unit Tests / Unit Tests Summary (push) Canceled after 0s
Publish no_rocm_image_ubuntu24_04 images / publish_no_rocm_image_ubuntu24_04_openmpi (push) Canceled after 0s
2795 lines
111 KiB
Markdown
2795 lines
111 KiB
Markdown
<!-- Packets are listed in alpabetical order, and if in a section, alphabetical
|
||
order within that section. -->
|
||
|
||
# GDB Remote Protocol Extensions
|
||
|
||
LLDB has added new GDB server packets to better support multi-threaded and
|
||
remote debugging. These extend the
|
||
[protocol defined by GDB ](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Packets.html#Packets) (and [this page](https://sourceware.org/gdb/current/onlinedocs/gdb.html/Host-I_002fO-Packets.html#Host-I_002fO-Packets) for `vFile` packets).
|
||
|
||
If a packet is restated here it is because LLDB's version has some behaviour
|
||
difference to GDB's version, or it provides some context for a following LLDB
|
||
extension packet.
|
||
|
||
Why did we add these? The most common reason is flexibility. Normally you need
|
||
to start the correct GDB and the correct GDB server when debugging. If you have
|
||
mismatch, then things go wrong very quickly. LLDB makes extensive use of the GDB
|
||
remote protocol and we wanted to make sure that the experience was a bit more
|
||
dynamic where we can discover information about a remote target without having
|
||
to know anything up front.
|
||
|
||
We also ran into performance issues with the existing GDB remote
|
||
protocol that can be overcome when using a reliable communications layer.
|
||
|
||
Some packets improve performance, others allow for remote process launching
|
||
(if you have an OS), and others allow us to dynamically figure out what
|
||
registers a thread might have. Again with GDB, both sides pre-agree on how the
|
||
registers will look (how many, their register number,name and offsets).
|
||
|
||
We prefer to be able to dynamically determine what kind of architecture, OS and
|
||
vendor we are debugging, as well as how things are laid out when it comes to
|
||
the thread register contexts.
|
||
|
||
## _M\<size\>,\<permissions\>
|
||
|
||
Allocate memory on the remote target with the specified size and
|
||
permissions.
|
||
|
||
The allocate memory packet starts with `_M<size>,<permissions>`. It returns a
|
||
raw big endian address value, or an empty response for unimplemented, or `EXX` for an error
|
||
code. The packet is formatted as:
|
||
```
|
||
char packet[256];
|
||
int packet_len;
|
||
packet_len = ::snprintf (
|
||
packet,
|
||
sizeof(packet),
|
||
"_M%zx,%s%s%s",
|
||
(size_t)size,
|
||
permissions & lldb::ePermissionsReadable ? "r" : "",
|
||
permissions & lldb::ePermissionsWritable ? "w" : "",
|
||
permissions & lldb::ePermissionsExecutable ? "x" : "");
|
||
```
|
||
|
||
You request a size and give the permissions. This packet does NOT need to be
|
||
implemented if you don't want to support running JITed code. The return value
|
||
is just the address of the newly allocated memory as raw big endian hex bytes.
|
||
|
||
**Priority To Implement:** High if you want LLDB to be able to JIT code and run
|
||
that code. JIT code also needs data which is also allocated and tracked. Low if
|
||
you don't support running JIT'ed code.
|
||
|
||
## _m\<addr\>
|
||
|
||
Deallocate memory that was previously allocated using an allocate
|
||
memory pack.
|
||
|
||
The deallocate memory packet is `_m<addr>` where you pass in the address you
|
||
got back from a previous call to the allocate memory packet. It returns `OK`
|
||
if the memory was successfully deallocated, or `EXX`" for an error, or an
|
||
empty response if not supported.
|
||
|
||
**Priority To Implement:** High if you want LLDB to be able to JIT code and run
|
||
that code. JIT code also needs data which is also allocated and tracked. Low if
|
||
you don't support running JIT'ed code.
|
||
|
||
## "A" - launch args packet
|
||
|
||
Launch a program using the supplied arguments
|
||
|
||
We have added support for the "set program arguments" packet where we can
|
||
start a connection to a remote server and then later supply the path to the
|
||
executable and the arguments to use when executing:
|
||
|
||
GDB remote docs for this:
|
||
```
|
||
set program arguments(reserved) Aarglen,argnum,arg,...
|
||
```
|
||
Where A is followed by the length in bytes of the hex encoded argument,
|
||
followed by an argument integer, and followed by the ASCII characters
|
||
converted into hex bytes for each arg:
|
||
```
|
||
send packet: $A98,0,2f566f6c756d65732f776f726b2f67636c6179746f6e2f446f63756d656e74732f7372632f6174746163682f612e6f7574#00
|
||
read packet: $OK#00
|
||
```
|
||
The above packet helps when you have remote debugging abilities where you
|
||
could launch a process on a remote host, this isn't needed for bare board
|
||
debugging.
|
||
|
||
**Priority To Implement:** Low. Only needed if the remote target wants to launch
|
||
a target after making a connection to a GDB server that isn't already connected to
|
||
an inferior process.
|
||
|
||
## "D" - Detach and stay stopped
|
||
|
||
We extended the "D" packet to specify that the monitor should keep the
|
||
target suspended on detach. The normal behavior is to resume execution
|
||
on detach. We will send:
|
||
```
|
||
qSupportsDetachAndStayStopped:
|
||
```
|
||
|
||
to query whether the monitor supports the extended detach, and if it does,
|
||
when we want the monitor to detach but not resume the target, we will
|
||
send:
|
||
```
|
||
D1
|
||
```
|
||
In any case, if we want the normal detach behavior we will just send:
|
||
```
|
||
D
|
||
```
|
||
|
||
## jGetDyldProcessState
|
||
|
||
This packet fetches the process launch state, as reported by libdyld on
|
||
Darwin systems, most importantly to indicate when the system libraries
|
||
have initialized sufficiently to safely call utility functions.
|
||
|
||
```
|
||
LLDB SENDS: jGetDyldProcessState
|
||
STUB REPLIES: {"process_state_value":48,"process_state string":"dyld_process_state_libSystem_initialized"}
|
||
```
|
||
|
||
**Priority To Implement:** Low. This packet is needed to prevent lldb's utility
|
||
functions for scanning the Objective-C class list from running very early in
|
||
process startup.
|
||
|
||
## jGetLoadedDynamicLibrariesInfos
|
||
|
||
This packet asks the remote debug stub to send the details about libraries
|
||
being added/removed from the process as a performance optimization.
|
||
|
||
There are two ways this packet can be used. Both return a dictionary of
|
||
binary images formatted the same way.
|
||
|
||
One requests information on all shared libraries:
|
||
```
|
||
jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true}
|
||
```
|
||
|
||
There are two additional keys that can be specified: the older
|
||
`"report_load_commands":false` which specifies that the detailed
|
||
information about the binary should not be included (the Mach-O
|
||
header and load commands), and the newer key that supplants
|
||
`report_load_commands`, `information-level` which takes a string
|
||
argument that is one of `address-only`, `address-name`,
|
||
`address-name-uuid`, `full`. `full` will include the details of
|
||
the mach header and segment virtual addresses for the binaries.
|
||
|
||
`"report_load_commands":false` is equivalent to
|
||
`"information-level":"address-only"`.
|
||
|
||
`information-level` allows the caller to limit the amount of data
|
||
being returned to one of (address, address+name, address+name+uuid,
|
||
full). When we first attach to a process, we may want to fetch the
|
||
binary addresses for all binaries loaded in the process, and then
|
||
fetch detailed information in batches, to keep the size of the
|
||
packets from becoming too large.
|
||
|
||
|
||
And the second form of jGetLoadedDynamicLibrariesInfos
|
||
requests information about a list of binaries, given their load addresses:
|
||
```
|
||
jGetLoadedDynamicLibrariesInfos:{"solib_addresses":[8382824135,3258302053,830202858503]}
|
||
```
|
||
|
||
The second call is both a performance optimization (instead of having lldb read the mach-o header/load commands
|
||
out of memory with generic read packets) but also adds additional information in the form of the
|
||
filename of the shared libraries (which is not available in the mach-o header/load commands.)
|
||
|
||
An example using the OS X 10.11 style call:
|
||
```
|
||
LLDB SENDS: jGetLoadedDynamicLibrariesInfos:{"image_count":1,"image_list_address":140734800075128}
|
||
STUB REPLIES: ${"images":[{"load_address":4294967296,"mod_date":0,"pathname":"/tmp/a.out","uuid":"02CF262C-ED6F-3965-9E14-63538B465CFF","mach_header":{"magic":4277009103,"cputype":16777223,"cpusubtype":18446744071562067971,"filetype":2},"segments":{"name":"__PAGEZERO","vmaddr":0,"vmsize":4294967296,"fileoff":0,"filesize":0,"maxprot":0},{"name":"__TEXT","vmaddr":4294967296,"vmsize":4096,"fileoff":0,"filesize":4096,"maxprot":7},{"name":"__LINKEDIT","vmaddr":4294971392,"vmsize":4096,"fileoff":4096,"filesize":152,"maxprot":7}}]}#00
|
||
```
|
||
|
||
Or pretty-printed:
|
||
```
|
||
STUB REPLIES: ${"images":
|
||
[
|
||
{"load_address":4294967296,
|
||
"mod_date":0,
|
||
"pathname":"/tmp/a.out",
|
||
"uuid":"02CF262C-ED6F-3965-9E14-63538B465CFF",
|
||
"mach_header":
|
||
{"magic":4277009103,
|
||
"cputype":16777223,
|
||
"cpusubtype":18446744071562067971,
|
||
"filetype":2
|
||
},
|
||
"segments":
|
||
[
|
||
{"name":"__PAGEZERO",
|
||
"vmaddr":0,
|
||
"vmsize":4294967296,
|
||
"fileoff":0,
|
||
"filesize":0,
|
||
"maxprot":0
|
||
},
|
||
{"name":"__TEXT",
|
||
"vmaddr":4294967296,
|
||
"vmsize":4096,
|
||
"fileoff":0,
|
||
"filesize":4096,
|
||
"maxprot":7
|
||
},
|
||
{"name":"__LINKEDIT",
|
||
"vmaddr":4294971392,
|
||
"vmsize":4096,
|
||
"fileoff":4096,
|
||
"filesize":152,
|
||
"maxprot":7
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
This is similar to the `qXfer:libraries:read` packet, and it could
|
||
be argued that it should be merged into that packet. A separate
|
||
packet was created primarily because lldb needs to specify the
|
||
number of images to be read and the address from which the initial
|
||
information is read. Also the XML DTD would need to be extended
|
||
quite a bit to provide all the information that the `DynamicLoaderMacOSX`
|
||
would need to work correctly on this platform.
|
||
|
||
**Priority To Implement:**
|
||
|
||
On OS X 10.11, iOS 9, tvOS 9, watchOS 2 and older: Low. If this packet is absent,
|
||
lldb will read the Mach-O headers/load commands out of memory.
|
||
On macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer: High. If this packet is absent,
|
||
lldb will not know anything about shared libraries in the inferior, or where the main
|
||
executable loaded.
|
||
|
||
## jGetSharedCacheInfo
|
||
|
||
This packet asks the remote debug stub to send the details about the inferior's
|
||
shared cache. The shared cache is a collection of common libraries/frameworks that
|
||
are mapped into every process at the same address on Darwin systems, and can be
|
||
identified by a load address and UUID.
|
||
|
||
```
|
||
LLDB SENDS: jGetSharedCacheInfo:{}
|
||
STUB REPLIES: ${"shared_cache_base_address":140735683125248,"shared_cache_uuid":"DDB8D70C-C9A2-3561-B2C8-BE48A4F33F96","no_shared_cache":false,"shared_cache_private_cache":false]}#00
|
||
```
|
||
|
||
**Priority To Implement:** Low
|
||
|
||
When both lldb and the inferior process are running on the same computer, and lldb
|
||
and the inferior process have the same shared cache, lldb may (as an optimization) read
|
||
the shared cache out of its own memory instead of using gdb-remote read packets to read
|
||
them from the inferior process.
|
||
|
||
## jModulesInfo:[{"file":"...",triple:"..."}, ...]
|
||
|
||
Get information for a list of modules by given module path and
|
||
architecture.
|
||
|
||
The response is a JSON array of dictionaries containing the following keys:
|
||
* `uuid`
|
||
* `triple`
|
||
* `file_path`
|
||
* `file_offset`
|
||
* `file_size`
|
||
|
||
The meaning of the fields is the same as in the `qModuleInfo` packet. The server
|
||
signals the failure to retrieve the module info for a file by ommiting the
|
||
corresponding array entry from the response. The server may also
|
||
include entries the client did not ask for, if it has reason to
|
||
the modules will be interesting to the client.
|
||
|
||
**Priority To Implement:** Optional. If not implemented, `qModuleInfo` packet
|
||
will be used, which may be slower if the target contains a large number of modules
|
||
and the communication link has a non-negligible latency.
|
||
|
||
## jLLDBTraceGetBinaryData
|
||
|
||
Get binary data given a trace technology and a data identifier.
|
||
The input is specified as a JSON object and the response has the same format
|
||
as the "binary memory read" (aka "x") packet. In case of failures, an error
|
||
message is returned.
|
||
|
||
```
|
||
send packet: jLLDBTraceGetBinaryData:{"type":<type>,"kind":<query>,"tid":<tid>,"offset":<offset>,"size":<size>}]
|
||
read packet: <binary data>/E<error code>;AAAAAAAAA
|
||
```
|
||
|
||
### Schema
|
||
|
||
The schema for the input is:
|
||
```
|
||
{
|
||
"type": <string>,
|
||
Tracing technology name, e.g. intel-pt, arm-etm.
|
||
"kind": <string>,
|
||
Identifier for the data.
|
||
"cpuId": <Optional decimal>,
|
||
Core id in decimal if the data belongs to a CPU core.
|
||
"tid"?: <Optional decimal>,
|
||
Tid in decimal if the data belongs to a thread.
|
||
}
|
||
```
|
||
|
||
## jLLDBTraceGetState
|
||
|
||
Get the current state of the process and its threads being traced by
|
||
a given trace technology. The response is a JSON object with custom
|
||
information depending on the trace technology. In case of errors, an
|
||
error message is returned.
|
||
|
||
```
|
||
send packet: jLLDBTraceGetState:{"type":<type>}]
|
||
read packet: {...object}/E<error code>;AAAAAAAAA
|
||
```
|
||
|
||
### Input Schema
|
||
|
||
```
|
||
{
|
||
"type": <string>
|
||
Tracing technology name, e.g. intel-pt, arm-etm.
|
||
}
|
||
```
|
||
|
||
### Output Schema
|
||
|
||
```
|
||
{
|
||
"tracedThreads": [{
|
||
"tid": <decimal integer>,
|
||
"binaryData": [
|
||
{
|
||
"kind": <string>,
|
||
Identifier for some binary data related to this thread to
|
||
fetch with the jLLDBTraceGetBinaryData packet.
|
||
"size": <decimal integer>,
|
||
Size in bytes of this thread data.
|
||
},
|
||
]
|
||
}],
|
||
"processBinaryData": [
|
||
{
|
||
"kind": <string>,
|
||
Identifier for some binary data related to this process to
|
||
fetch with the jLLDBTraceGetBinaryData packet.
|
||
"size": <decimal integer>,
|
||
Size in bytes of this thread data.
|
||
},
|
||
],
|
||
"cpus"?: [
|
||
"id": <decimal integer>,
|
||
Identifier for this CPU logical core.
|
||
"binaryData": [
|
||
{
|
||
"kind": <string>,
|
||
Identifier for some binary data related to this thread to
|
||
fetch with the jLLDBTraceGetBinaryData packet.
|
||
"size": <decimal integer>,
|
||
Size in bytes of this cpu core data.
|
||
},
|
||
]
|
||
],
|
||
"warnings"?: [<string>],
|
||
Non-fatal messages useful for troubleshooting.
|
||
|
||
... other attributes specific to the given tracing technology
|
||
}
|
||
```
|
||
|
||
**Note:** `tracedThreads` includes all threads traced by both "process tracing"
|
||
and "thread tracing".
|
||
|
||
### Intel Pt
|
||
|
||
If per-cpu process tracing is enabled, "tracedThreads" will contain all
|
||
the threads of the process without any trace buffers. Besides that, the
|
||
"cpus" field will also be returned with per cpu core trace buffers.
|
||
A side effect of per-cpu tracing is that all the threads of unrelated
|
||
processes will also be traced, thus polluting the tracing data.
|
||
|
||
Binary data kinds:
|
||
- iptTrace: trace buffer for a thread or a cpu.
|
||
- perfContextSwitchTrace: context switch trace for a cpu generated by
|
||
perf_event_open.
|
||
- procfsCpuInfo: contents of the /proc/cpuinfo file.
|
||
|
||
Additional attributes:
|
||
* tscPerfZeroConversion
|
||
* This field allows converting Intel processor's TSC values to nanoseconds.
|
||
It is available through the Linux perf_event API when cap_user_time and cap_user_time_zero
|
||
are set.
|
||
See the documentation of time_zero in
|
||
https://man7.org/linux/man-pages/man2/perf_event_open.2.html for more information about
|
||
the calculation and the meaning of the values in the schema below.
|
||
|
||
Schema for this field:
|
||
```
|
||
"tscPerfZeroConversion": {
|
||
"timeMult": <decimal integer>,
|
||
"timeShift": <decimal integer>,
|
||
"timeZero": <decimal integer>,
|
||
}
|
||
```
|
||
|
||
## jLLDBTraceStart
|
||
|
||
Start tracing a process or its threads using a provided tracing technology.
|
||
The input and output are specified as JSON objects. In case of success, an OK
|
||
response is returned, or an error otherwise.
|
||
|
||
### Process Tracing
|
||
|
||
This traces existing and future threads of the current process. An error is
|
||
returned if the process is already being traced.
|
||
|
||
```
|
||
send packet: jLLDBTraceStart:{"type":<type>,...other params}]
|
||
read packet: OK/E<error code>;AAAAAAAAA
|
||
```
|
||
|
||
### Thread Tracing
|
||
|
||
This traces specific threads.
|
||
|
||
```
|
||
send packet: jLLDBTraceStart:{"type":<type>,"tids":<tids>,...other params}]
|
||
read packet: OK/E<error code>;AAAAAAAAA
|
||
```
|
||
|
||
### Input Schema
|
||
|
||
```
|
||
{
|
||
"type": <string>,
|
||
Tracing technology name, e.g. intel-pt, arm-etm.
|
||
|
||
/* thread tracing only */
|
||
"tids"?: [<decimal integer>],
|
||
Individual threads to trace.
|
||
|
||
... other parameters specific to the provided tracing type
|
||
}
|
||
```
|
||
|
||
**Notes:**
|
||
- If "tids" is not provided, then the operation is "process tracing",
|
||
otherwise it's "thread tracing".
|
||
- Each tracing technology can have different levels of support for "thread
|
||
tracing" and "process tracing".
|
||
|
||
### Intel-Pt
|
||
|
||
intel-pt supports both "thread tracing" and "process tracing".
|
||
|
||
"Process tracing" is implemented in two different ways. If the
|
||
"perCpuTracing" option is false, then each thread is traced individually
|
||
but managed by the same "process trace" instance. This means that the
|
||
amount of trace buffers used is proportional to the number of running
|
||
threads. This is the recommended option unless the number of threads is
|
||
huge. If "perCpuTracing" is true, then each cpu core is traced invidually
|
||
instead of each thread, which uses a fixed number of trace buffers, but
|
||
might result in less data available for less frequent threads. See
|
||
"perCpuTracing" below for more information.
|
||
|
||
Each actual intel pt trace buffer, either from "process tracing" or "thread
|
||
tracing", is stored in an in-memory circular buffer, which keeps the most
|
||
recent data.
|
||
|
||
Additional params in the input schema:
|
||
```
|
||
{
|
||
"iptTraceSize": <decimal integer>,
|
||
Size in bytes used by each individual per-thread or per-cpu trace
|
||
buffer. It must be a power of 2 greater than or equal to 4096 (2^12)
|
||
bytes.
|
||
|
||
"enableTsc": <boolean>,
|
||
Whether to enable TSC timestamps or not. This is supported on
|
||
all devices that support intel-pt. A TSC timestamp is generated along
|
||
with PSB (synchronization) packets, whose frequency can be configured
|
||
with the "psbPeriod" parameter.
|
||
|
||
"psbPeriod"?: <Optional decimal integer>,
|
||
This value defines the period in which PSB packets will be generated.
|
||
A PSB packet is a synchronization packet that contains a TSC
|
||
timestamp and the current absolute instruction pointer.
|
||
|
||
This parameter can only be used if
|
||
|
||
/sys/bus/event_source/devices/intel_pt/caps/psb_cyc
|
||
|
||
is 1. Otherwise, the PSB period will be defined by the processor.
|
||
|
||
If supported, valid values for this period can be found in
|
||
|
||
/sys/bus/event_source/devices/intel_pt/caps/psb_periods
|
||
|
||
which contains a hexadecimal number, whose bits represent valid
|
||
values e.g. if bit 2 is set, then value 2 is valid.
|
||
|
||
The psb_period value is converted to the approximate number of
|
||
raw trace bytes between PSB packets as:
|
||
|
||
2 ^ (value + 11)
|
||
|
||
e.g. value 3 means 16KiB between PSB packets. Defaults to
|
||
0 if supported.
|
||
|
||
/* process tracing only */
|
||
"perCpuTracing": <boolean>
|
||
Instead of having an individual trace buffer per thread, this option
|
||
triggers the collection on a per cpu core basis. This effectively
|
||
traces the entire activity on all cores. At decoding time, in order
|
||
to correctly associate a decoded instruction with a thread, the
|
||
context switch trace of each core is needed, as well as a record per
|
||
cpu indicating which thread was running on each core when tracing
|
||
started. These secondary traces are correlated with the intel-pt
|
||
trace by comparing TSC timestamps.
|
||
|
||
This option forces the capture of TSC timestamps (see "enableTsc").
|
||
|
||
Note: This option can't be used simulatenously with any other trace
|
||
sessions because of its system-wide nature.
|
||
|
||
/* process tracing only */
|
||
"processBufferSizeLimit": <decimal integer>,
|
||
Maximum total buffer size per process in bytes.
|
||
This limit applies to the sum of the sizes of all thread or cpu core
|
||
buffers for the current process, excluding the ones started with
|
||
"thread tracing".
|
||
|
||
If "perCpuTracing" is false, whenever a thread is attempted to be
|
||
traced due to "process tracing" and the limit would be reached, the
|
||
process is stopped with a "tracing" reason along with a meaningful
|
||
description, so that the user can retrace the process if needed.
|
||
|
||
If "perCpuTracing" is true, then starting the system-wide trace
|
||
session fails if all the individual per-cpu trace buffers require
|
||
in total more memory that the limit impossed by this parameter.
|
||
}
|
||
```
|
||
|
||
Notes:
|
||
- Modifying the parameters of an existing trace is not supported. The user
|
||
needs to stop the trace and start a new one.
|
||
- If "process tracing" is attempted and there are individual threads
|
||
already being traced with "thread tracing", these traces are left
|
||
unaffected and the threads not traced twice.
|
||
- If "thread tracing" is attempted on a thread already being traced with
|
||
either "thread tracing" or "process tracing", it fails.
|
||
|
||
## jLLDBTraceStop
|
||
|
||
Stop tracing a process or its threads using a provided tracing technology.
|
||
The input and output are specified as JSON objects. In case of success, an OK
|
||
response is returned, or an error otherwise.
|
||
|
||
### Process Trace Stopping
|
||
|
||
Stopping a process trace stops the active traces initiated with
|
||
"thread tracing".
|
||
|
||
```
|
||
send packet: jLLDBTraceStop:{"type":<type>}]
|
||
read packet: OK/E<error code>;AAAAAAAAA
|
||
```
|
||
|
||
### Thread Trace Stopping
|
||
|
||
This is a best effort request, which tries to stop as many traces as
|
||
possible.
|
||
|
||
```
|
||
send packet: jLLDBTraceStop:{"type":<type>,"tids":<tids>}]
|
||
read packet: OK/E<error code>;AAAAAAAAA
|
||
```
|
||
|
||
### Input Schema
|
||
|
||
The schema for the input is
|
||
```
|
||
{
|
||
"type": <string>
|
||
Tracing technology name, e.g. intel-pt, arm-etm.
|
||
|
||
/* thread trace stopping only */
|
||
"tids": [<decimal integer>]
|
||
Individual thread traces to stop.
|
||
}
|
||
```
|
||
|
||
**Note:** If `tids` is not provided, then the operation is "process trace stopping".
|
||
|
||
### Intel Pt
|
||
|
||
Stopping a specific thread trace started with "process tracing" is allowed.
|
||
|
||
## jLLDBTraceSupported
|
||
|
||
Get the processor tracing type supported by the gdb-server for the current
|
||
inferior. Responses might be different depending on the architecture and
|
||
capabilities of the underlying OS.
|
||
|
||
```
|
||
send packet: jLLDBTraceSupported
|
||
read packet: {"name":<name>, "description":<description>}/E<error code>;AAAAAAAAA
|
||
```
|
||
|
||
### Output Schema
|
||
|
||
```
|
||
{
|
||
"name": <string>,
|
||
Tracing technology name, e.g. intel-pt, arm-etm.
|
||
"description": <string>,
|
||
Description for this technology.
|
||
}
|
||
```
|
||
|
||
If no tracing technology is supported for the inferior, or no process is
|
||
running, then an error message is returned.
|
||
|
||
**Note:** This packet is used by Trace plug-ins (see `lldb_private::Trace.h`) to
|
||
do live tracing. Specifically, the name of the plug-in should match the name
|
||
of the tracing technology returned by this packet.
|
||
|
||
## jMultiBreakpoint
|
||
|
||
This packet allows setting and removing multiple breakpoints in one go. It
|
||
lists multiple `Z` and `z` packets using a JSON array of strings.
|
||
Formally:
|
||
|
||
```
|
||
$jMultiBreakpoint:{"breakpoint_requests" : ["request"[,"request"]*]}
|
||
```
|
||
|
||
Where each `request` is one of:
|
||
|
||
```
|
||
* z0,addr,kind
|
||
* z1,addr,kind
|
||
* z2,addr,kind
|
||
* z3,addr,kind
|
||
* z4,addr,kind
|
||
* Z0,addr,kind[;cond_list…][;cmds:persist,cmd_list…]
|
||
* Z1,addr,kind[;cond_list…][;cmds:persist,cmd_list…]
|
||
* Z2,addr,kind
|
||
* Z3,addr,kind
|
||
* Z4,addr,kind
|
||
```
|
||
|
||
Each field has the same meaning as the corresponding packet in the GDB Remote
|
||
Protocol.
|
||
|
||
For example, the packet below is a request to set one breakpoint and to remove
|
||
two others:
|
||
|
||
```
|
||
$jMultiBreakpoint: {"breakpoint_requests": ["Z0,1025783e8,4", "z0,1025783ec,4", "z0,1025783e8,4"]}
|
||
```
|
||
|
||
The same address may be specified multiple times.
|
||
|
||
The stub must execute the sequence of `request`s in the order they
|
||
appear in the `jMultiBreakpoint` packet. This is not an atomic operation:
|
||
individual requests may fail, and the stub must process subsequent requests
|
||
regardless of previous failures.
|
||
|
||
The reply consists of a JSON dictionary with a single entry, `results`, which
|
||
is an array of strings, with the same contents allowed by a reply to a `z` or
|
||
`Z` packet.
|
||
|
||
```
|
||
{"results": ["OK", "E03", "OK"]}
|
||
```
|
||
|
||
A stub that supports this packet must include `jMultiBreakpoint+` in the reply
|
||
to `qSupported`.
|
||
|
||
**Priority To Implement:** Low. This is a performance optimization, reducing
|
||
the number of packets sent when manipulating breakpoints.
|
||
|
||
## jThreadExtendedInfo
|
||
|
||
This packet, which takes its arguments as JSON and sends its reply as
|
||
JSON, allows the gdb remote stub to provide additional information
|
||
about a given thread.
|
||
|
||
This packet takes its arguments in [JSON](http://www.json.org).
|
||
At a minimum, a thread must be specified, for example:
|
||
```
|
||
jThreadExtendedInfo:{"thread":612910}
|
||
```
|
||
|
||
Because this is a JSON string, the thread number is provided in base 10.
|
||
Additional key-value pairs may be provided by lldb to the gdb remote
|
||
stub. For instance, on some versions of macOS, lldb can read offset
|
||
information out of the system libraries. Using those offsets, debugserver
|
||
is able to find the Thread Specific Address (TSD) for a thread and include
|
||
that in the return information. So lldb will send these additional fields
|
||
like so:
|
||
```
|
||
jThreadExtendedInfo:{"plo_pthread_tsd_base_address_offset":0,"plo_pthread_tsd_base_offset":224,"plo_pthread_tsd_entry_size":8,"thread":612910}
|
||
```
|
||
|
||
There are no requirements for what is included in the response. A simple
|
||
reply on a OS X Yosemite / iOS 8 may include the pthread_t value, the
|
||
Thread Specific Data (TSD) address, the dispatch_queue_t value if the thread
|
||
is associated with a GCD queue, and the requested Quality of Service (QoS)
|
||
information about that thread. For instance, a reply may look like:
|
||
```
|
||
{"tsd_address":4371349728,"requested_qos":{"enum_value":33,"constant_name":"QOS_CLASS_USER_INTERACTIVE","printable_name":"User Interactive"},"pthread_t":4371349504,"dispatch_queue_t":140735087127872}
|
||
```
|
||
|
||
`tsd_address`, `pthread_t`, and `dispatch_queue_t` are all simple key-value pairs.
|
||
The JSON standard requires that numbers be expressed in base 10 - so all of
|
||
these are. `requested_qos` is a dictionary with three key-value pairs in it -
|
||
so the UI layer may choose the form most appropriate for displaying to the user.
|
||
|
||
Sending JSON over gdb-remote protocol introduces some problems. We may be
|
||
sending strings with arbitrary contents in them, including the `#`, `$`, and `*`
|
||
characters that have special meaning in gdb-remote protocol and cannot occur
|
||
in the middle of the string. The standard solution for this would be to require
|
||
ascii-hex encoding of all strings, or ascii-hex encode the entire JSON payload.
|
||
|
||
Instead, the binary escaping convention is used for JSON data. This convention
|
||
(e.g. used for the `X` packet) says that if `#`, `$`, `*`, or `}` are to occur in
|
||
the payload, the character `}` (`0x7d`) is emitted, then the metacharacter is emitted
|
||
xor'ed by `0x20`. The `}` character occurs in every JSON payload at least once, and
|
||
`} ^ 0x20` happens to be `]` so the raw packet characters for a request will look
|
||
like:
|
||
```
|
||
jThreadExtendedInfo:{"thread":612910}]
|
||
```
|
||
|
||
**Priority To Implement:** Low. This packet is only needed if the gdb remote stub
|
||
wants to provide interesting additional information about a thread for the user.
|
||
|
||
## jThreadsInfo
|
||
|
||
Ask for the server for thread stop information of all threads.
|
||
|
||
The data in this packet is very similar to the stop reply packets, but is packaged in
|
||
JSON and uses JSON arrays where applicable. The JSON output looks like:
|
||
```
|
||
[
|
||
{ "tid":1580681,
|
||
"metype":6,
|
||
"medata":[2,0],
|
||
"reason":"exception",
|
||
"qaddr":140735118423168,
|
||
"registers": {
|
||
"0":"8000000000000000",
|
||
"1":"0000000000000000",
|
||
"2":"20fabf5fff7f0000",
|
||
"3":"e8f8bf5fff7f0000",
|
||
"4":"0100000000000000",
|
||
"5":"d8f8bf5fff7f0000",
|
||
"6":"b0f8bf5fff7f0000",
|
||
"7":"20f4bf5fff7f0000",
|
||
"8":"8000000000000000",
|
||
"9":"61a8db78a61500db",
|
||
"10":"3200000000000000",
|
||
"11":"4602000000000000",
|
||
"12":"0000000000000000",
|
||
"13":"0000000000000000",
|
||
"14":"0000000000000000",
|
||
"15":"0000000000000000",
|
||
"16":"960b000001000000",
|
||
"17":"0202000000000000",
|
||
"18":"2b00000000000000",
|
||
"19":"0000000000000000",
|
||
"20":"0000000000000000"
|
||
},
|
||
"memory":[
|
||
{"address":140734799804592,"bytes":"c8f8bf5fff7f0000c9a59e8cff7f0000"},
|
||
{"address":140734799804616,"bytes":"00000000000000000100000000000000"}
|
||
]
|
||
}
|
||
]
|
||
```
|
||
|
||
It contains an array of dictionaries with all of the key value pairs that are
|
||
normally in the stop reply packet, including the expedited registers. The registers are
|
||
passed as hex-encoded JSON string in debuggee-endian byte order. Note that the register
|
||
numbers are decimal numbers, unlike the stop-reply packet, where they are written in
|
||
hex. The packet also contains expedited memory in the `memory` key. This allows the
|
||
server to expedite memory that the client is likely to use (e.g., areas around the
|
||
stack pointer, which are needed for computing backtraces) and it reduces the packet
|
||
count.
|
||
|
||
When a thread has hit the binaries-loaded lldb internal breakpoint
|
||
(if the server can detect that), the server may expedite information
|
||
about the binaries that have been loaded, to reduce packet traffic
|
||
that would immediately follow. The key `added-binaries` will have
|
||
a value of an array of binary addresses. The key `detailed-binaries-info`
|
||
will have a value of a JSON dictionary which is the reply that
|
||
`jGetLoadedDynamicLibrariesInfos` would return for these binaries,
|
||
so lldb doesn't need to request it.
|
||
|
||
On macOS with debugserver, we expedite the frame pointer backchain for a thread
|
||
(up to 256 entries) by reading 2 pointers worth of bytes at the frame pointer (for
|
||
the previous FP and PC), and follow the backchain. Most backtraces on macOS and
|
||
iOS now don't require us to read any memory.
|
||
|
||
An expedited register may have an empty string as its value (`"21":""`)
|
||
which indicates that the register cannot be read at this current
|
||
stop point, and lldb should not try to read the register value with
|
||
a separate `p` read-register request, it will not succeed.
|
||
|
||
**Priority To Implement:** Low
|
||
|
||
This is a performance optimization, which speeds up debugging by avoiding
|
||
multiple round-trips for retrieving thread information. The information from this
|
||
packet can be retrieved using a combination of `qThreadStopInfo` and `m` packets.
|
||
|
||
### MultiMemRead
|
||
|
||
Read memory from multiple memory ranges.
|
||
|
||
This packet has one argument:
|
||
|
||
* `ranges`: a list of pairs of numbers, formatted in base-16. Each pair is
|
||
separated by a `,`, as is each number in each pair. The first number of the
|
||
pair denotes the base address of the memory read, the second denotes the number
|
||
of bytes to be read. The list must end with a `;`.
|
||
|
||
The reply packet starts with a comma-separated list of numbers formatted in
|
||
base-16, denoting how many bytes were read from each range, in the same order
|
||
as the request packet. The list is followed by a `;`, followed by a sequence of
|
||
bytes containing binary encoded data for all memory that was read. The length
|
||
of the binary encodeed data, after being decoded as required by the GDB remote
|
||
protocol, must be equal to the sum of the numbers provided at the start of the
|
||
reply. The order of the binary data is the same as the order of the ranges in
|
||
the request packet.
|
||
|
||
If some part of a range is not readable, the stub may perform a partial read of
|
||
a prefix of the range. In other words, partial reads will only ever be from the
|
||
start of the range, never the middle or end. Support for partial reads depends
|
||
on the debug stub.
|
||
|
||
If, by applying the rules above, the stub has read zero bytes from a range, it
|
||
must return a length of zero for that range in the reply packet; no bytes for
|
||
this memory range are included in the sequence of bytes that follows.
|
||
|
||
A stub that supports this packet must include `MultiMemRead+` in the reply to
|
||
`qSupported`.
|
||
|
||
```
|
||
send packet: $MultiMemRead:ranges:100a00,4,200200,a0,400000,4;
|
||
read packet: $4,0,2;<binary encoding of abcd1000><binary encoding of eeff>
|
||
```
|
||
|
||
In the example above, the first read produced `abcd1000`, the read of `a0`
|
||
bytes from address `200200` failed to read any bytes, and the third read
|
||
produced two bytes – `eeff` – out of the four requested.
|
||
|
||
```
|
||
send packet: $MultiMemRead:ranges:100a00,0;
|
||
read packet: $0;
|
||
```
|
||
|
||
In the example above, a read of zero bytes was requested.
|
||
|
||
**Priority to Implement:** Only required for performance, the debugger will
|
||
fall back to doing separate read requests if this packet is unavailable.
|
||
|
||
## QEnvironment:NAME=VALUE
|
||
|
||
Setup the environment up for a new child process that will soon be
|
||
launched using the "A" packet.
|
||
|
||
NB: key/value pairs are sent as-is so gdb-remote protocol meta characters
|
||
(e.g. `#` or `$`) are not acceptable. If any non-printable or
|
||
metacharacters are present in the strings, `QEnvironmentHexEncoded`
|
||
should be used instead if it is available. If you don't want to
|
||
scan the environment strings before sending, prefer
|
||
the `QEnvironmentHexEncoded` packet over `QEnvironment`, if it is
|
||
available.
|
||
|
||
Both GDB and LLDB support passing down environment variables. Is it ok to
|
||
respond with a `$#00` (unimplemented):
|
||
```
|
||
send packet: $QEnvironment:ACK_COLOR_FILENAME=bold yellow#00
|
||
read packet: $OK#00
|
||
```
|
||
This packet can be sent one or more times _prior_ to sending a "A" packet.
|
||
|
||
**Priority To Implement:** Low. Only needed if the remote target wants to launch
|
||
a target after making a connection to a GDB server that isn't already connected to
|
||
an inferior process.
|
||
|
||
## QEnvironmentHexEncoded:HEX-ENCODING(NAME=VALUE)
|
||
|
||
Setup the environment up for a new child process that will soon be
|
||
launched using the "A" packet.
|
||
|
||
The only difference between this packet and `QEnvironment` is that the
|
||
environment key-value pair is ascii hex encoded for transmission.
|
||
This allows values with gdb-remote metacharacters like `#` to be sent.
|
||
|
||
Both GDB and LLDB support passing down environment variables. Is it ok to
|
||
respond with a `$#00` (unimplemented):
|
||
```
|
||
send packet: $QEnvironment:41434b5f434f4c4f525f46494c454e414d453d626f6c642379656c6c6f77#00
|
||
read packet: $OK#00
|
||
```
|
||
This packet can be sent one or more times _prior_ to sending a "A" packet.
|
||
|
||
**Priority To Implement:** Low. Only needed if the remote target wants to launch
|
||
a target after making a connection to a GDB server that isn't already connected to
|
||
an inferior process.
|
||
|
||
## QEnableCompression
|
||
|
||
This packet enables compression of the packets that the debug stub sends to lldb.
|
||
If the debug stub can support compression, it indictes this in the reply of the
|
||
"qSupported" packet. For example:
|
||
```
|
||
LLDB SENDS: qSupported:xmlRegisters=i386,arm,mips
|
||
STUB REPLIES: qXfer:features:read+;SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;
|
||
```
|
||
|
||
If lldb knows how to use any of these compression algorithms, it can ask that this
|
||
compression mode be enabled.
|
||
```
|
||
QEnableCompression:type:zlib-deflate;
|
||
```
|
||
|
||
The debug stub should reply with an uncompressed `OK` packet to indicate that the
|
||
request was accepted. All further packets the stub sends will use this compression.
|
||
|
||
Packets are compressed as the last step before they are sent from the stub, and
|
||
decompressed as the first step after they are received. The packet format in compressed
|
||
mode becomes one of two:
|
||
```
|
||
$N<uncompressed payload>#00
|
||
|
||
$C<size of uncompressed payload in base 10>:<compressed payload>#00
|
||
```
|
||
|
||
Where `#00` is the actual checksum value if noack mode is not enabled. The checksum
|
||
value is for the `N<uncompressed payload>` or
|
||
`C<size of uncompressed payload in base 10>:<compressed payload>` bytes in the packet.
|
||
|
||
The size of the uncompressed payload in base 10 is provided because it will simplify
|
||
decompression if the final buffer size needed is known ahead of time.
|
||
|
||
Compression on low-latency connections is unlikely to be an improvement. Particularly
|
||
when the debug stub and lldb are running on the same host. It should only be used
|
||
for slow connections, and likely only for larger packets.
|
||
|
||
Example compression algorithms that may be used include:
|
||
* `zlib-deflate` -
|
||
The raw DEFLATE format as described in IETF RFC 1951. With the ZLIB library, you
|
||
can compress to this format with an initialization like
|
||
deflateInit2 (&stream, 5, Z_DEFLATED, -15, 8, Z_DEFAULT_STRATEGY)
|
||
and you can decompress with an initialization like
|
||
inflateInit2 (&stream, -15).
|
||
* `lz4` -
|
||
https://en.wikipedia.org/wiki/LZ4_(compression_algorithm)
|
||
https://github.com/Cyan4973/lz4
|
||
The libcompression APIs on darwin systems call this `COMPRESSION_LZ4_RAW`.
|
||
* `lzfse` -
|
||
Compression algorithm added in macOS 10.11, with open source C reference
|
||
implementation on github.
|
||
https://en.wikipedia.org/wiki/LZFSE
|
||
https://github.com/lzfse/lzfse
|
||
* `lzma` -
|
||
libcompression implements "LZMA level 6", the default compression for the
|
||
open source LZMA implementation.
|
||
|
||
|
||
## QEnableErrorStrings
|
||
|
||
This packet enables reporting of Error strings in remote packet
|
||
replies from the server to client. If the server supports this
|
||
feature, it should send an OK response.
|
||
|
||
```
|
||
send packet: $QEnableErrorStrings
|
||
read packet: $OK#00
|
||
```
|
||
|
||
The client can expect the following error replies if this feature is enabled in
|
||
the server:
|
||
```
|
||
EXX;AAAAAAAAA
|
||
```
|
||
where `AAAAAAAAA` will be a hex encoded ASCII string.
|
||
`XX`` is hex encoded byte number.
|
||
|
||
It must be noted that even if the client has enabled reporting
|
||
strings in error replies, it must not expect error strings to all
|
||
error replies.
|
||
|
||
**Priority To Implement:** Low. Only needed if the remote target wants to
|
||
provide strings that are human readable along with an error code.
|
||
|
||
## QLaunchArch
|
||
|
||
Set the architecture to use when launching a process for hosts that can run
|
||
multiple architecture slices that are contained in a single universal program
|
||
file.
|
||
|
||
```
|
||
send packet: $QLaunchArch:<architecture>
|
||
```
|
||
|
||
The response is `OK` if the value in `<architecture>` was recognised as valid
|
||
and will be used for the next launch request. `E63` if not.
|
||
|
||
**Priority To Implement:** Only required for hosts that support program files
|
||
that contain code for multiple architectures.
|
||
|
||
## QListThreadsInStopReply
|
||
|
||
Enable the `threads:` and `thread-pcs:` data in the question-mark packet
|
||
("T packet") responses when the stub reports that a program has
|
||
stopped executing.
|
||
|
||
```
|
||
send packet: QListThreadsInStopReply
|
||
read packet: OK
|
||
```
|
||
|
||
**Priority To Implement:** Performance. This is a performance benefit to lldb
|
||
if the thread id's and thread pc values are provided to lldb in the T stop packet
|
||
-- if they are not provided to lldb, lldb will likely need to send one to
|
||
two packets per thread to fetch the data at every private stop.
|
||
|
||
## QRestoreRegisterState:\<save_id\> / QRestoreRegisterState:\<save_id\>;thread:XXXX;
|
||
|
||
The `QRestoreRegisterState` packet tells the remote debugserver to
|
||
restore all registers using the `save_id` which is an unsigned
|
||
integer that was returned from a previous call to
|
||
`QSaveRegisterState`. The restoration process can only be done once
|
||
as the data backing the register state will be freed upon the
|
||
completion of the `QRestoreRegisterState` command.
|
||
|
||
If thread suffixes are enabled the second form of this packet is
|
||
used, otherwise the first form is used.
|
||
|
||
The response is either:
|
||
* `OK` - if all registers were successfully restored
|
||
* `EXX` - for any errors
|
||
|
||
**Priority To Implement:** Low, this is mostly a convenience packet to avoid
|
||
having to send all registers with a `g` packet. It should only be implemented
|
||
if support for the `QSaveRegisterState` is added.
|
||
|
||
## QSaveRegisterState / QSaveRegisterState;thread:XXXX;
|
||
|
||
The `QSaveRegisterState` packet tells the remote debugserver to save
|
||
all registers and return a non-zero unique integer ID that
|
||
represents these save registers. If thread suffixes are enabled the
|
||
second form of this packet is used, otherwise the first form is
|
||
used. This packet is called prior to executing an expression, so
|
||
the remote GDB server should do anything it needs to in order to
|
||
ensure the registers that are saved are correct. On macOS this
|
||
involves calling `thread_abort_safely(mach_port_t thread)` to
|
||
ensure we get the correct registers for a thread in case it is
|
||
currently having code run on its behalf in the kernel.
|
||
|
||
The response is either:
|
||
* `<unsigned int>` - The save_id result is a non-zero unsigned integer value
|
||
that can be passed back to the GDB server using a
|
||
`QRestoreRegisterState` packet to restore the registers
|
||
one time.
|
||
* `EXX` - or an error code in the form of `EXX` where `XX` is a
|
||
hex error code.
|
||
|
||
**Priority To Implement:** Low, this is mostly a convenience packet to avoid
|
||
having to send all registers with a `g` packet. It should only be implemented if
|
||
support for the `QRestoreRegisterState` is added.
|
||
|
||
## QSetDetachOnError
|
||
|
||
Sets what the server should do when the communication channel with LLDB
|
||
goes down. Either kill the inferior process (`0`) or remove breakpoints and
|
||
detach (`1`).
|
||
|
||
The data in this packet is a single a character, which should be `0` if the
|
||
inferior process should be killed, or `1` if the server should remove all
|
||
breakpoints and detach from the inferior.
|
||
|
||
**Priority To Implement:** Low. Only required if the target wants to keep the
|
||
inferior process alive when the communication channel goes down.
|
||
|
||
## QSetDisableASLR:\<bool\>
|
||
|
||
Enable or disable ASLR on the next "A" packet.
|
||
|
||
Or control if ASLR is enabled/disabled:
|
||
```
|
||
send packet: QSetDisableASLR:1
|
||
read packet: OK
|
||
|
||
send packet: QSetDisableASLR:0
|
||
read packet: OK
|
||
```
|
||
This packet must be sent _prior_ to sending a "A" packet.
|
||
|
||
**Priority To Implement:** Low. Only needed if the remote target wants to launch
|
||
a target after making a connection to a GDB server that isn't already connected to
|
||
an inferior process and if the target supports disabling ASLR
|
||
(Address space layout randomization).
|
||
|
||
## QSetSTDIN:\<ascii-hex-path\> / QSetSTDOUT:\<ascii-hex-path\> / QSetSTDERR:\<ascii-hex-path\>
|
||
|
||
Setup where STDIN, STDOUT, and STDERR go prior to sending an "A"
|
||
packet.
|
||
|
||
When launching a program through the GDB remote protocol with the "A" packet,
|
||
you might also want to specify where stdin/out/err go:
|
||
```
|
||
QSetSTDIN:<ascii-hex-path>
|
||
QSetSTDOUT:<ascii-hex-path>
|
||
QSetSTDERR:<ascii-hex-path>
|
||
```
|
||
These packets must be sent _prior_ to sending a "A" packet.
|
||
|
||
**Priority To Implement:** Low. Only needed if the remote target wants to launch
|
||
a target after making a connection to a GDB server that isn't already connected to
|
||
an inferior process.
|
||
|
||
## QSetWorkingDir:\<ascii-hex-path\>
|
||
|
||
Set the working directory prior to sending an "A" packet.
|
||
|
||
Or specify the working directory:
|
||
```
|
||
QSetWorkingDir:<ascii-hex-path>
|
||
```
|
||
This packet must be sent _prior_ to sending a "A" packet.
|
||
|
||
**Priority To Implement:** Low. Only needed if the remote target wants to launch
|
||
a target after making a connection to a GDB server that isn't already connected to
|
||
an inferior process.
|
||
|
||
## QStartNoAckMode
|
||
|
||
Try to enable no ACK mode to skip sending ACKs and NACKs.
|
||
|
||
Having to send an ACK/NACK after every packet slows things down a bit, so we
|
||
have a way to disable ACK packets to minimize the traffic for reliable
|
||
communication interfaces (like sockets). Below GDB or LLDB will send this
|
||
packet to try and disable ACKs. All lines that start with "send packet: " are
|
||
from GDB/LLDB, and all lines that start with "read packet: " are from the GDB
|
||
remote server:
|
||
```
|
||
send packet: $QStartNoAckMode#b0
|
||
read packet: +
|
||
read packet: $OK#9a
|
||
send packet: +
|
||
```
|
||
|
||
**Priority To Implement:** High. Any GDB remote server that can implement this
|
||
should if the connection is reliable. This improves packet throughput and increases
|
||
the performance of the connection.
|
||
|
||
## QSupported
|
||
|
||
Query the GDB remote server for features it supports
|
||
|
||
QSupported is a standard GDB Remote Serial Protocol packet, but
|
||
there are several additions to the response that lldb can parse.
|
||
They are not all listed here.
|
||
|
||
An example exchange:
|
||
```
|
||
send packet: qSupported:xmlRegisters=i386,arm,mips,arc;multiprocess+;fork-events+;vfork-events+
|
||
|
||
read packet: qXfer:features:read+;PacketSize=20000;qEcho+;native-signals+;SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;SupportedWatchpointTypes=aarch64-mask,aarch64-bas;
|
||
```
|
||
|
||
In the example above, three lldb extensions are shown:
|
||
|
||
* `PacketSize=20000`
|
||
* The base 16 maximum packet size that the stub can handle.
|
||
* `SupportedCompressions=<item,item,...>`
|
||
* A list of compression types that the stub can use to compress packets
|
||
when the QEnableCompression packet is used to request one of them.
|
||
* `SupportedWatchpointTypes=<item,item,...>`
|
||
* A list of watchpoint types that this stub can manage. Currently defined
|
||
names are:
|
||
* `x86_64` - 64-bit x86-64 watchpoints (1, 2, 4, 8 byte watchpoints
|
||
aligned to those amounts)
|
||
* `aarch64-bas` AArch64 Byte Address Select watchpoints
|
||
(any number of contiguous bytes within a doubleword)
|
||
* `aarch64-mask` AArch64 MASK watchpoints
|
||
(any power-of-2 region of memory from 8 to 2GB, aligned)
|
||
|
||
If nothing is specified, lldb will default to sending power-of-2
|
||
watchpoints, up to a pointer size, `sizeof(void*)`, a reasonable
|
||
baseline assumption.
|
||
|
||
**Priority To Implement:** Optional
|
||
|
||
## QThreadSuffixSupported
|
||
|
||
Try to enable thread suffix support for the `g`, `G`, `p`, and `P` packets.
|
||
|
||
When reading thread registers, you currently need to set the current
|
||
thread, then read the registers. This is kind of cumbersome, so we added the
|
||
ability to query if the remote GDB server supports adding a `thread:<tid>;`
|
||
suffix to all packets that request information for a thread. To test if the
|
||
remote GDB server supports this feature:
|
||
```
|
||
send packet: $QThreadSuffixSupported#00
|
||
read packet: OK
|
||
```
|
||
|
||
If `OK` is returned, then the `g`, `G`, `p` and `P` packets can accept a
|
||
thread suffix. So to send a `g` packet (read all register values):
|
||
```
|
||
send packet: $g;thread:<tid>;#00
|
||
read packet: ....
|
||
|
||
send packet: $G;thread:<tid>;#00
|
||
read packet: ....
|
||
|
||
send packet: $p1a;thread:<tid>;#00
|
||
read packet: ....
|
||
|
||
send packet: $P1a=1234abcd;thread:<tid>;#00
|
||
read packet: ....
|
||
```
|
||
|
||
otherwise, without this you would need to always send two packets:
|
||
```
|
||
send packet: $Hg<tid>#00
|
||
read packet: ....
|
||
send packet: $g#00
|
||
read packet: ....
|
||
```
|
||
|
||
We also added support for allocating and deallocating memory. We use this to
|
||
allocate memory so we can run JITed code.
|
||
|
||
**Priority To Implement:** High
|
||
|
||
Adding a thread suffix allows us to read and write registers
|
||
more efficiently and stops us from having to select a thread with
|
||
one packet and then read registers with a second packet. It also
|
||
makes sure that no errors can occur where the debugger thinks it
|
||
already has a thread selected (see the `Hg` packet from the standard
|
||
GDB remote protocol documentation) yet the remote GDB server actually
|
||
has another thread selected.
|
||
|
||
## qAttachOrWaitSupported
|
||
|
||
This is a binary "is it supported" query. Return OK if you support
|
||
`vAttachOrWait`.
|
||
|
||
**Priority To Implement:** Low. This is required if you support `vAttachOrWait`,
|
||
otherwise no support is needed since the standard "I don't recognize this packet"
|
||
response will do the right thing.
|
||
|
||
## qFileLoadAddress:\<file_path\>
|
||
|
||
Get the load address of a memory mapped file.
|
||
The load address is defined as the address of the first memory
|
||
region what contains data mapped from the specified file.
|
||
|
||
The response is either:
|
||
* `<unsigned-hex64>` - Load address of the file in big endian encoding
|
||
* `E01` - the requested file isn't loaded
|
||
* `EXX` - for any other errors
|
||
|
||
**Priority To Implement:** Low, required if dynamic linker don't fill in the load
|
||
address of some object file in the rendezvous data structure.
|
||
|
||
## qfProcessInfo / qsProcessInfo (Platform Extension)
|
||
|
||
Get the first process info (`qfProcessInfo`) or subsequent process
|
||
info (`qsProcessInfo`) for one or more processes on the remote
|
||
platform. The first call gets the first match and subsequent calls
|
||
to `qsProcessInfo` gets the subsequent matches. Return an error `EXX`,
|
||
where `XX` are two hex digits, when no more matches are available.
|
||
|
||
The `qfProcessInfo` packet can be followed by a `:` and
|
||
some key value pairs. The key value pairs in the command are:
|
||
* `name` - `ascii-hex` -
|
||
An ASCII hex string that contains the name of the process that will be matched.
|
||
* `name_match` - `enum` -
|
||
One of:
|
||
* `equals`
|
||
* `starts_with`
|
||
* `ends_with`
|
||
* `contains`
|
||
* `regex`
|
||
* `pid` - `integer`- A string value containing the decimal process ID
|
||
* `parent_pid` - `integer` - A string value containing the decimal parent process ID
|
||
* `uid` - `integer` - A string value containing the decimal user ID
|
||
* `gid` - `integer` - A string value containing the decimal group ID
|
||
* `euid` - `integer` - A string value containing the decimal effective user ID
|
||
* `egid` - `integer` - A string value containing the decimal effective group ID
|
||
* `all_users` - `bool` -
|
||
A boolean value that specifies if processes should
|
||
be listed for all users, not just the user that the
|
||
platform is running as
|
||
* `triple` - `string` -
|
||
An ASCII triple string (`x86_64`, `x86_64-apple-macosx`, `armv7-apple-ios`)
|
||
* `args` - `string` -
|
||
A string value containing the process arguments separated by the character `-`,
|
||
where each argument is hex-encoded. It includes `argv[0]`.
|
||
|
||
The response consists of key/value pairs where the key is separated from the
|
||
values with colons and each pair is terminated with a semi colon. For a list
|
||
of the key/value pairs in the response see the `qProcessInfoPID` packet
|
||
documentation.
|
||
|
||
Sample packet/response:
|
||
```
|
||
send packet: $qfProcessInfo#00
|
||
read packet: $pid:60001;ppid:59948;uid:7746;gid:11;euid:7746;egid:11;name:6c6c6462;triple:x86_64-apple-macosx;#00
|
||
send packet: $qsProcessInfo#00
|
||
read packet: $pid:59992;ppid:192;uid:7746;gid:11;euid:7746;egid:11;name:6d64776f726b6572;triple:x86_64-apple-macosx;#00
|
||
send packet: $qsProcessInfo#00
|
||
read packet: $E04#00
|
||
```
|
||
|
||
**Priority To Implement:** Required
|
||
|
||
|
||
## qGDBServerVersion
|
||
|
||
Get version information about this implementation of the gdb-remote
|
||
protocol.
|
||
|
||
The goal of this packet is to provide enough information about an
|
||
implementation of the gdb-remote-protocol server that lldb can
|
||
work around implementation problems that are discovered after the
|
||
version has been released/deployed. The name and version number
|
||
should be sufficiently unique that lldb can unambiguously identify
|
||
the origin of the program (for instance, debugserver from lldb) and
|
||
the version/submission number/patch level of the program - whatever
|
||
is appropriate for your server implementation.
|
||
|
||
The packet follows the key-value pair model, semicolon separated.
|
||
```
|
||
send packet: $qGDBServerVersion#00
|
||
read packet: $name:debugserver;version:310.2;#00
|
||
```
|
||
|
||
Other clients may find other key-value pairs to be useful for identifying
|
||
a gdb stub. Patch level, release name, build number may all be keys that
|
||
better describe your implementation's version.
|
||
|
||
Suggested key names:
|
||
* `name`: the name of your remote server - "debugserver" is the lldb standard
|
||
implementation
|
||
* `version`: identifies the version number of this server
|
||
* `patch_level`: the patch level of this server
|
||
* `release_name`: the name of this release, if your project uses names
|
||
* `build_number`: if you use a build system with increasing build numbers,
|
||
this may be the right key name for your server
|
||
* `major_version`: major version number
|
||
* `minor_version`: minor version number
|
||
|
||
**Priority To Implement:** High. This packet is usually very easy to implement
|
||
and can help LLDB to work around bugs in a server's implementation when they
|
||
are found.
|
||
|
||
## qGetWorkingDir
|
||
|
||
Get the current working directory of the platform stub in
|
||
ASCII hex encoding.
|
||
|
||
```
|
||
receive: qGetWorkingDir
|
||
send: 2f4170706c65496e7465726e616c2f6c6c64622f73657474696e67732f342f5465737453657474696e67732e746573745f646973617373656d626c65725f73657474696e6773
|
||
```
|
||
|
||
## qHostInfo
|
||
|
||
Get information about the host we are remotely connected to.
|
||
|
||
LLDB supports a host info call that gets all sorts of details of the system
|
||
that is being debugged:
|
||
```
|
||
send packet: $qHostInfo#00
|
||
read packet: $cputype:16777223;cpusubtype:3;ostype:darwin;vendor:apple;endian:little;ptrsize:8;#00
|
||
```
|
||
|
||
Key value pairs are one of:
|
||
* `cputype`: is a number that is the mach-o CPU type that is being debugged (base 10)
|
||
* `cpusubtype`: is a number that is the mach-o CPU subtype type that is being debugged (base 10)
|
||
* `triple`: a string for the target triple (x86_64-apple-macosx) that can be used to specify arch + vendor + os in one entry
|
||
* `vendor`: a string for the vendor (apple), not needed if "triple" is specified
|
||
* `ostype`: a string for the OS being debugged (macosx, linux, freebsd, ios, watchos), not needed if "triple" is specified
|
||
* `endian`: is one of "little", "big", or "pdp"
|
||
* `ptrsize`: an unsigned number that represents how big pointers are in bytes on the debug target
|
||
* `hostname`: the hostname of the host that is running the GDB server if available
|
||
* `os_build`: a string for the OS build for the remote host as a string value
|
||
* `os_kernel`: a string describing the kernel version
|
||
* `os_version`: a version string that represents the current OS version (10.8.2)
|
||
* `watchpoint_exceptions_received`: one of "before" or "after" to specify if a watchpoint is triggered before or after the pc when it stops
|
||
* `default_packet_timeout`: an unsigned number that specifies the default timeout in seconds
|
||
* `distribution_id`: optional. For linux, specifies distribution id (e.g. ubuntu, fedora, etc.)
|
||
* `osmajor`: optional, specifies the major version number of the OS (e.g. for macOS 10.12.2, it would be 10)
|
||
* `osminor`: optional, specifies the minor version number of the OS (e.g. for macOS 10.12.2, it would be 12)
|
||
* `ospatch`: optional, specifies the patch level number of the OS (e.g. for macOS 10.12.2, it would be 2)
|
||
* `vm-page-size`: optional, specifies the target system VM page size, base 10.
|
||
Needed for the "dirty-pages:" list in the qMemoryRegionInfo
|
||
packet, where a list of dirty pages is sent from the remote
|
||
stub. This page size tells lldb how large each dirty page is.
|
||
* `addressing_bits`: optional, specifies how many bits in addresses are
|
||
significant for addressing, base 10. If bits 38..0
|
||
in a 64-bit pointer are significant for addressing,
|
||
then the value is 39. This is needed on e.g. AArch64
|
||
v8.3 ABIs that use pointer authentication, so lldb
|
||
knows which bits to clear/set to get the actual
|
||
addresses.
|
||
* `low_mem_addressing_bits`: optional, specifies how many bits in
|
||
addresses in low memory are significant for addressing, base 10.
|
||
AArch64 can have different page table setups for low and high
|
||
memory, and therefore a different number of bits used for addressing.
|
||
* `high_mem_addressing_bits`: optional, specifies how many bits in
|
||
addresses in high memory are significant for addressing, base 10.
|
||
AArch64 can have different page table setups for low and high
|
||
memory, and therefore a different number of bits used for addressing.
|
||
|
||
**Priority To Implement:** High. This packet is usually very easy to implement
|
||
and can help LLDB select the correct plug-ins for the job based on the target
|
||
triple information that is supplied.
|
||
|
||
## qKillSpawnedProcess (Platform Extension)
|
||
|
||
Kill a process running on the target system.
|
||
|
||
```
|
||
receive: qKillSpawnedProcess:1337
|
||
send: OK
|
||
```
|
||
The request packet has the process ID in base 10.
|
||
|
||
## qLaunchGDBServer (Platform Extension)
|
||
|
||
Have the remote platform launch a GDB server.
|
||
|
||
The `qLaunchGDBServer` packet must be followed by a `:` and
|
||
some key value pairs. The key value pairs in the command are:
|
||
* `port` - `integer` -
|
||
A string value containing the decimal port ID or zero if the port should be
|
||
bound and returned
|
||
* `host` - `integer` -
|
||
The host that connections should be limited to when the GDB server is connected to.
|
||
|
||
Sample packet/response:
|
||
```
|
||
send packet: $qLaunchGDBServer:port:0;host:lldb.apple.com;#00
|
||
read packet: $pid:60025;port:50776;#00
|
||
```
|
||
|
||
The `pid` key/value pair is only specified if the remote platform launched
|
||
a separate process for the GDB remote server and can be omitted if no
|
||
process was separately launched.
|
||
|
||
The `port` key/value pair in the response lets clients know what port number
|
||
to attach to in case zero was specified as the "port" in the sent command.
|
||
|
||
**Priority To Implement:** Required
|
||
|
||
|
||
## qLaunchSuccess
|
||
|
||
Check whether launching a process with the `A` packet succeeded.
|
||
|
||
Returns the status of the last attempt to launch a process.
|
||
Either `OK` if no error ocurred, or `E` followed by a string
|
||
describing the error.
|
||
|
||
**Priority To Implement:** High, launching processes is a key part of LLDB's
|
||
platform mode.
|
||
|
||
## qMemoryRegionInfo:\<addr\>
|
||
|
||
Get information about the address range that contains `<addr>`.
|
||
|
||
We added a way to get information for a memory region. The packet is:
|
||
```
|
||
qMemoryRegionInfo:<addr>
|
||
```
|
||
|
||
Where `<addr>` is a big endian hex address. The response is returned in a series
|
||
of tuples like the data returned in a stop reply packet. The currently valid
|
||
tuples to return are:
|
||
* `start:<start-addr>;` - `<start-addr>` is a big endian hex address that is
|
||
the start address of the range that contains `<addr>`
|
||
* `size:<size>;` - `<size>` is a big endian hex byte size of the address
|
||
of the range that contains `<addr>`
|
||
* `permissions:<permissions>;` - `<permissions>` is a string that contains one
|
||
or more of the characters from `rwx`
|
||
* `name:<name>;` - `<name>` is a hex encoded string that contains the name of
|
||
the memory region mapped at the given address. In case of
|
||
regions backed by a file it have to be the absolute path of
|
||
the file while for anonymous regions it have to be the name
|
||
associated to the region if that is available.
|
||
* `flags:<flags-string>;` - where `<flags-string>` is a space separated string
|
||
of flag names. Currently the only supported flag
|
||
is `mt` for AArch64 memory tagging. lldb will
|
||
ignore any other flags in this field.
|
||
* `type:[<type>][,<type>];` - memory types that apply to this region, e.g.
|
||
`stack` for stack memory.
|
||
* `error:<ascii-byte-error-string>;` - where `<ascii-byte-error-string>` is
|
||
a hex encoded string value that
|
||
contains an error string
|
||
* `dirty-pages:[<hexaddr>][,<hexaddr];` -
|
||
A list of memory pages within this
|
||
region that are "dirty" -- they have been modified.
|
||
Page addresses are in base 16. The size of a page can
|
||
be found from the `qHostInfo`'s `page-size` key-value.
|
||
|
||
If the stub supports identifying dirty pages within a
|
||
memory region, this key should always be present for all
|
||
`qMemoryRegionInfo` replies. This key with no pages
|
||
listed (`dirty-pages:;`) indicates no dirty pages in
|
||
this memory region. The *absence* of this key means
|
||
that this stub cannot determine dirty pages.
|
||
* `protection-key:<key>` - where `<key>` is an unsigned integer memory
|
||
protection key.
|
||
|
||
If the address requested is not in a mapped region (e.g. we've jumped through
|
||
a NULL pointer and are at 0x0) currently lldb expects to get back the size
|
||
of the unmapped region -- that is, the distance to the next valid region.
|
||
For instance, with a macOS process which has nothing mapped in the first
|
||
4GB of its address space, if we're asking about address 0x2:
|
||
```
|
||
qMemoryRegionInfo:2
|
||
start:2;size:fffffffe;
|
||
```
|
||
|
||
The lack of `permissions:` indicates that none of read/write/execute are valid
|
||
for this region.
|
||
|
||
The stub must include `permissions:` key-value on all memory ranges
|
||
that are valid to access in the inferior process -- the lack of
|
||
`permissions:` means that this is an inaccessible (no page table
|
||
entries exist, in a system using VM) memory range. If a stub cannot
|
||
determine actual permissions, return `rwx`.
|
||
|
||
**Priority To Implement:** Medium
|
||
|
||
This is nice to have, but it isn't necessary. It helps LLDB
|
||
do stack unwinding when we branch into memory that isn't executable.
|
||
If we can detect that the code we are stopped in isn't executable,
|
||
then we can recover registers for stack frames above the current
|
||
frame. Otherwise we must assume we are in some JIT'ed code (not JIT
|
||
code that LLDB has made) and assume that no registers are available
|
||
in higher stack frames.
|
||
|
||
## qModuleInfo:\<module_path\>;\<arch triple\>
|
||
|
||
Get information for a module by given module path and architecture.
|
||
|
||
The response is either:
|
||
* `(uuid|md5):...;triple:...;file_offset:...;file_size...;`
|
||
* `EXX` - for any errors
|
||
|
||
**Priority To Implement:** Optional, required if dynamic loader cannot fetch
|
||
module's information like UUID directly from inferior's memory.
|
||
|
||
## qPathComplete (Platform Extension)
|
||
|
||
Get a list of matched disk files/directories by passing a boolean flag
|
||
and a partial path.
|
||
|
||
```
|
||
receive: qPathComplete:0,6d61696e
|
||
send: M6d61696e2e637070
|
||
receive: qPathComplete:1,746573
|
||
send: M746573742f,74657374732f
|
||
```
|
||
|
||
If the first argument is zero, the result should contain all
|
||
files (including directories) starting with the given path. If the
|
||
argument is one, the result should contain only directories.
|
||
|
||
The result should be a comma-separated list of hex-encoded paths.
|
||
Paths denoting a directory should end with a directory separator (`/` or `\`.
|
||
|
||
|
||
## qPlatform_mkdir
|
||
|
||
Creates a new directory on the connected remote machine.
|
||
|
||
Request: `qPlatform_mkdir:<hex-file-mode>,<ascii-hex-path>`
|
||
|
||
The request packet has the fields:
|
||
1. mode bits in base 16
|
||
2. file path in ascii-hex encoding
|
||
|
||
Reply:
|
||
* `F<mkdir-return-code>`
|
||
(mkdir called successfully and returned with the given return code)
|
||
* `Exx` (An error occurred)
|
||
|
||
**Priority To Implement:** Low
|
||
|
||
## qPlatform_shell
|
||
|
||
Run a command in a shell on the connected remote machine.
|
||
|
||
The request consists of the command to be executed encoded in ASCII characters
|
||
converted into hex bytes.
|
||
|
||
The response to this packet consists of the letter F followed by the return code,
|
||
followed by the signal number (or 0 if no signal was delivered), and escaped bytes
|
||
of captured program output.
|
||
|
||
Below is an example communication from a client sending an "ls -la" command:
|
||
```
|
||
send packet: $qPlatform_shell:6c73202d6c61,00000002#ec
|
||
read packet: $F,00000000,00000000,total 4736
|
||
drwxrwxr-x 16 username groupname 4096 Aug 15 21:36 .
|
||
drwxr-xr-x 17 username groupname 4096 Aug 10 16:39 ..
|
||
-rw-rw-r-- 1 username groupname 73875 Aug 12 16:46 notes.txt
|
||
drwxrwxr-x 5 username groupname 4096 Aug 15 21:36 source.cpp
|
||
-rw-r--r-- 1 username groupname 2792 Aug 12 16:46 a.out
|
||
-rw-r--r-- 1 username groupname 3190 Aug 12 16:46 Makefile
|
||
```
|
||
|
||
**Priority To Implement:** High
|
||
|
||
## qProcessInfo
|
||
|
||
Get information about the process we are currently debugging.
|
||
|
||
**Priority To Implement:** Medium
|
||
|
||
On systems which can launch multiple different architecture processes,
|
||
the qHostInfo may not disambiguate sufficiently to know what kind of
|
||
process is being debugged.
|
||
|
||
For example on a 64-bit x86 Mac system both 32-bit and 64-bit user processes are possible,
|
||
and with Mach-O universal files, the executable file may contain both 32- and
|
||
64-bit slices so it may be impossible to know until you're attached to a real
|
||
process to know what you're working with.
|
||
|
||
All numeric fields return base 16 numbers without any "0x" prefix.
|
||
|
||
An i386 process:
|
||
```
|
||
send packet: $qProcessInfo#00
|
||
read packet: $pid:42a8;parent-pid:42bf;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:7;cpusubtype:3;ostype:macosx;vendor:apple;endian:little;ptrsize:4;#00
|
||
```
|
||
|
||
An x86_64 process:
|
||
```
|
||
send packet: $qProcessInfo#00
|
||
read packet: $pid:d22c;parent-pid:d34d;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:1000007;cpusubtype:3;ostype:macosx;vendor:apple;endian:little;ptrsize:8;#00
|
||
```
|
||
|
||
Key value pairs include:
|
||
* `pid`: the process id
|
||
* `parent-pid`: the process of the parent process (often debugserver will become the parent when attaching)
|
||
* `real-uid`: the real user id of the process
|
||
* `real-gid`: the real group id of the process
|
||
* `effective-uid`: the effective user id of the process
|
||
* `effective-gid`: the effective group id of the process
|
||
* `cputype`: the Mach-O CPU type of the process (base 16)
|
||
* `cpusubtype`: the Mach-O CPU subtype of the process (base 16)
|
||
* `ostype`: is a string the represents the OS being debugged (darwin, linux, freebsd)
|
||
* `vendor`: is a string that represents the vendor (apple)
|
||
* `endian`: is one of "little", "big", or "pdp"
|
||
* `ptrsize`: is a number that represents how big pointers are in bytes
|
||
* `main-binary-uuid`: is the UUID of a firmware type binary that the gdb stub knows about
|
||
* `main-binary-address`: is the load address of the firmware type binary
|
||
* `main-binary-slide`: is the slide of the firmware type binary, if address isn't known
|
||
* `binary-addresses`: A comma-separated list of binary load addresses base 16.
|
||
lldb will parse the binaries in memory to get UUIDs, then
|
||
try to find the binaries & debug info by UUID. Intended for
|
||
use with a small number of firmware type binaries where the
|
||
search for binary/debug info may be expensive.
|
||
|
||
## qProcessInfoPID:PID (Platform Extension)
|
||
|
||
Have the remote platform get detailed information on a process by
|
||
ID. PID is specified as a decimal integer.
|
||
|
||
The response consists of key/value pairs where the key is separated from the
|
||
values with colons and each pair is terminated with a semi colon.
|
||
|
||
The key value pairs in the response are:
|
||
* `pid` - `integer` - Process ID as a decimal integer string
|
||
* `ppid` - `integer` - Parent process ID as a decimal integer string
|
||
* `uid` - `integer` - A string value containing the decimal user ID
|
||
* `gid` - `integer` - A string value containing the decimal group ID
|
||
* `euid` - `integer` - A string value containing the decimal effective user ID
|
||
* `egid` - `integer` - A string value containing the decimal effective group ID
|
||
* `name` - `ascii-hex` - An ASCII hex string that contains the name of the process
|
||
* `triple` - `string` - A target triple (`x86_64-apple-macosx`, `armv7-apple-ios`)
|
||
|
||
Sample packet/response:
|
||
```
|
||
send packet: $qProcessInfoPID:60050#00
|
||
read packet: $pid:60050;ppid:59948;uid:7746;gid:11;euid:7746;egid:11;name:6c6c6462;triple:x86_64-apple-macosx;#00
|
||
```
|
||
|
||
**Priority To Implement:** Optional
|
||
|
||
## qQueryGDBServer
|
||
|
||
Ask the platform for the list of gdbservers we have to connect
|
||
|
||
If the remote platform automatically started one or more gdbserver instance (without
|
||
lldb asking it) then it have to return the list of port number or socket name for
|
||
each of them what can be used by lldb to connect to those instances.
|
||
|
||
The data in this packet is a JSON array of JSON objects with the following keys:
|
||
* `port`: `<the port number to connect>` (optional)
|
||
* `socket_name`: `<the name of the socket to connect>` (optional)
|
||
|
||
Example packet:
|
||
```
|
||
[
|
||
{ "port": 1234 },
|
||
{ "port": 5432 },
|
||
{ "socket_name": "foo" }
|
||
]
|
||
```
|
||
|
||
**Priority To Implement:** Low
|
||
|
||
The packet is required to support connecting to gdbserver started
|
||
by the platform instance automatically.
|
||
|
||
## qRegisterInfo\<hex-reg-id\>
|
||
|
||
Discover register information from the remote GDB server.
|
||
|
||
With LLDB, for register information, remote GDB servers can add
|
||
support for the "qRegisterInfoN" packet where "N" is a zero based
|
||
base 16 register number that must start at zero and increase by one
|
||
for each register that is supported. The response is done in typical
|
||
GDB remote fashion where a series of "KEY:VALUE;" pairs are returned.
|
||
An example for the x86_64 registers is included below:
|
||
```
|
||
send packet: $qRegisterInfo0#00
|
||
read packet: $name:rax;bitsize:64;offset:0;encoding:uint;format:hex;set:General Purpose Registers;gcc:0;dwarf:0;#00
|
||
send packet: $qRegisterInfo1#00
|
||
read packet: $name:rbx;bitsize:64;offset:8;encoding:uint;format:hex;set:General Purpose Registers;gcc:3;dwarf:3;#00
|
||
send packet: $qRegisterInfo2#00
|
||
read packet: $name:rcx;bitsize:64;offset:16;encoding:uint;format:hex;set:General Purpose Registers;gcc:2;dwarf:2;#00
|
||
send packet: $qRegisterInfo3#00
|
||
read packet: $name:rdx;bitsize:64;offset:24;encoding:uint;format:hex;set:General Purpose Registers;gcc:1;dwarf:1;#00
|
||
send packet: $qRegisterInfo4#00
|
||
read packet: $name:rdi;bitsize:64;offset:32;encoding:uint;format:hex;set:General Purpose Registers;gcc:5;dwarf:5;#00
|
||
send packet: $qRegisterInfo5#00
|
||
read packet: $name:rsi;bitsize:64;offset:40;encoding:uint;format:hex;set:General Purpose Registers;gcc:4;dwarf:4;#00
|
||
send packet: $qRegisterInfo6#00
|
||
read packet: $name:rbp;alt-name:fp;bitsize:64;offset:48;encoding:uint;format:hex;set:General Purpose Registers;gcc:6;dwarf:6;generic:fp;#00
|
||
send packet: $qRegisterInfo7#00
|
||
read packet: $name:rsp;alt-name:sp;bitsize:64;offset:56;encoding:uint;format:hex;set:General Purpose Registers;gcc:7;dwarf:7;generic:sp;#00
|
||
send packet: $qRegisterInfo8#00
|
||
read packet: $name:r8;bitsize:64;offset:64;encoding:uint;format:hex;set:General Purpose Registers;gcc:8;dwarf:8;#00
|
||
send packet: $qRegisterInfo9#00
|
||
read packet: $name:r9;bitsize:64;offset:72;encoding:uint;format:hex;set:General Purpose Registers;gcc:9;dwarf:9;#00
|
||
send packet: $qRegisterInfoa#00
|
||
read packet: $name:r10;bitsize:64;offset:80;encoding:uint;format:hex;set:General Purpose Registers;gcc:10;dwarf:10;#00
|
||
send packet: $qRegisterInfob#00
|
||
read packet: $name:r11;bitsize:64;offset:88;encoding:uint;format:hex;set:General Purpose Registers;gcc:11;dwarf:11;#00
|
||
send packet: $qRegisterInfoc#00
|
||
read packet: $name:r12;bitsize:64;offset:96;encoding:uint;format:hex;set:General Purpose Registers;gcc:12;dwarf:12;#00
|
||
send packet: $qRegisterInfod#00
|
||
read packet: $name:r13;bitsize:64;offset:104;encoding:uint;format:hex;set:General Purpose Registers;gcc:13;dwarf:13;#00
|
||
send packet: $qRegisterInfoe#00
|
||
read packet: $name:r14;bitsize:64;offset:112;encoding:uint;format:hex;set:General Purpose Registers;gcc:14;dwarf:14;#00
|
||
send packet: $qRegisterInfof#00
|
||
read packet: $name:r15;bitsize:64;offset:120;encoding:uint;format:hex;set:General Purpose Registers;gcc:15;dwarf:15;#00
|
||
send packet: $qRegisterInfo10#00
|
||
read packet: $name:rip;alt-name:pc;bitsize:64;offset:128;encoding:uint;format:hex;set:General Purpose Registers;gcc:16;dwarf:16;generic:pc;#00
|
||
send packet: $qRegisterInfo11#00
|
||
read packet: $name:rflags;alt-name:flags;bitsize:64;offset:136;encoding:uint;format:hex;set:General Purpose Registers;#00
|
||
send packet: $qRegisterInfo12#00
|
||
read packet: $name:cs;bitsize:64;offset:144;encoding:uint;format:hex;set:General Purpose Registers;#00
|
||
send packet: $qRegisterInfo13#00
|
||
read packet: $name:fs;bitsize:64;offset:152;encoding:uint;format:hex;set:General Purpose Registers;#00
|
||
send packet: $qRegisterInfo14#00
|
||
read packet: $name:gs;bitsize:64;offset:160;encoding:uint;format:hex;set:General Purpose Registers;#00
|
||
send packet: $qRegisterInfo15#00
|
||
read packet: $name:fctrl;bitsize:16;offset:176;encoding:uint;format:hex;set:Floating Point Registers;#00
|
||
send packet: $qRegisterInfo16#00
|
||
read packet: $name:fstat;bitsize:16;offset:178;encoding:uint;format:hex;set:Floating Point Registers;#00
|
||
send packet: $qRegisterInfo17#00
|
||
read packet: $name:ftag;bitsize:8;offset:180;encoding:uint;format:hex;set:Floating Point Registers;#00
|
||
send packet: $qRegisterInfo18#00
|
||
read packet: $name:fop;bitsize:16;offset:182;encoding:uint;format:hex;set:Floating Point Registers;#00
|
||
send packet: $qRegisterInfo19#00
|
||
read packet: $name:fioff;bitsize:32;offset:184;encoding:uint;format:hex;set:Floating Point Registers;#00
|
||
send packet: $qRegisterInfo1a#00
|
||
read packet: $name:fiseg;bitsize:16;offset:188;encoding:uint;format:hex;set:Floating Point Registers;#00
|
||
send packet: $qRegisterInfo1b#00
|
||
read packet: $name:fooff;bitsize:32;offset:192;encoding:uint;format:hex;set:Floating Point Registers;#00
|
||
send packet: $qRegisterInfo1c#00
|
||
read packet: $name:foseg;bitsize:16;offset:196;encoding:uint;format:hex;set:Floating Point Registers;#00
|
||
send packet: $qRegisterInfo1d#00
|
||
read packet: $name:mxcsr;bitsize:32;offset:200;encoding:uint;format:hex;set:Floating Point Registers;#00
|
||
send packet: $qRegisterInfo1e#00
|
||
read packet: $name:mxcsrmask;bitsize:32;offset:204;encoding:uint;format:hex;set:Floating Point Registers;#00
|
||
send packet: $qRegisterInfo1f#00
|
||
read packet: $name:stmm0;bitsize:80;offset:208;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:33;dwarf:33;#00
|
||
send packet: $qRegisterInfo20#00
|
||
read packet: $name:stmm1;bitsize:80;offset:224;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:34;dwarf:34;#00
|
||
send packet: $qRegisterInfo21#00
|
||
read packet: $name:stmm2;bitsize:80;offset:240;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:35;dwarf:35;#00
|
||
send packet: $qRegisterInfo22#00
|
||
read packet: $name:stmm3;bitsize:80;offset:256;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:36;dwarf:36;#00
|
||
send packet: $qRegisterInfo23#00
|
||
read packet: $name:stmm4;bitsize:80;offset:272;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:37;dwarf:37;#00
|
||
send packet: $qRegisterInfo24#00
|
||
read packet: $name:stmm5;bitsize:80;offset:288;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:38;dwarf:38;#00
|
||
send packet: $qRegisterInfo25#00
|
||
read packet: $name:stmm6;bitsize:80;offset:304;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:39;dwarf:39;#00
|
||
send packet: $qRegisterInfo26#00
|
||
read packet: $name:stmm7;bitsize:80;offset:320;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:40;dwarf:40;#00
|
||
send packet: $qRegisterInfo27#00
|
||
read packet: $name:xmm0;bitsize:128;offset:336;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:17;dwarf:17;#00
|
||
send packet: $qRegisterInfo28#00
|
||
read packet: $name:xmm1;bitsize:128;offset:352;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:18;dwarf:18;#00
|
||
send packet: $qRegisterInfo29#00
|
||
read packet: $name:xmm2;bitsize:128;offset:368;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:19;dwarf:19;#00
|
||
send packet: $qRegisterInfo2a#00
|
||
read packet: $name:xmm3;bitsize:128;offset:384;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:20;dwarf:20;#00
|
||
send packet: $qRegisterInfo2b#00
|
||
read packet: $name:xmm4;bitsize:128;offset:400;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:21;dwarf:21;#00
|
||
send packet: $qRegisterInfo2c#00
|
||
read packet: $name:xmm5;bitsize:128;offset:416;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:22;dwarf:22;#00
|
||
send packet: $qRegisterInfo2d#00
|
||
read packet: $name:xmm6;bitsize:128;offset:432;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:23;dwarf:23;#00
|
||
send packet: $qRegisterInfo2e#00
|
||
read packet: $name:xmm7;bitsize:128;offset:448;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:24;dwarf:24;#00
|
||
send packet: $qRegisterInfo2f#00
|
||
read packet: $name:xmm8;bitsize:128;offset:464;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:25;dwarf:25;#00
|
||
send packet: $qRegisterInfo30#00
|
||
read packet: $name:xmm9;bitsize:128;offset:480;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:26;dwarf:26;#00
|
||
send packet: $qRegisterInfo31#00
|
||
read packet: $name:xmm10;bitsize:128;offset:496;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:27;dwarf:27;#00
|
||
send packet: $qRegisterInfo32#00
|
||
read packet: $name:xmm11;bitsize:128;offset:512;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:28;dwarf:28;#00
|
||
send packet: $qRegisterInfo33#00
|
||
read packet: $name:xmm12;bitsize:128;offset:528;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:29;dwarf:29;#00
|
||
send packet: $qRegisterInfo34#00
|
||
read packet: $name:xmm13;bitsize:128;offset:544;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:30;dwarf:30;#00
|
||
send packet: $qRegisterInfo35#00
|
||
read packet: $name:xmm14;bitsize:128;offset:560;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:31;dwarf:31;#00
|
||
send packet: $qRegisterInfo36#00
|
||
read packet: $name:xmm15;bitsize:128;offset:576;encoding:vector;format:vector-uint8;set:Floating Point Registers;gcc:32;dwarf:32;#00
|
||
send packet: $qRegisterInfo37#00
|
||
read packet: $name:trapno;bitsize:32;offset:696;encoding:uint;format:hex;set:Exception State Registers;#00
|
||
send packet: $qRegisterInfo38#00
|
||
read packet: $name:err;bitsize:32;offset:700;encoding:uint;format:hex;set:Exception State Registers;#00
|
||
send packet: $qRegisterInfo39#00
|
||
read packet: $name:faultvaddr;bitsize:64;offset:704;encoding:uint;format:hex;set:Exception State Registers;#00
|
||
send packet: $qRegisterInfo3a#00
|
||
read packet: $E45#00
|
||
```
|
||
|
||
As we see above we keep making subsequent calls to the remote server to
|
||
discover all registers by increasing the number appended to `qRegisterInfo` and
|
||
we get a response back that is a series of `key=value;` strings.
|
||
|
||
The `offset:` fields should not leave a gap anywhere in the g/G packet -- the
|
||
register values should be appended one after another. For instance, if the
|
||
register context for a thread looks like:
|
||
```
|
||
struct rctx {
|
||
uint32_t gpr1; // offset 0
|
||
uint32_t gpr2; // offset 4
|
||
uint32_t gpr3; // offset 8
|
||
uint64_t fp1; // offset 16
|
||
};
|
||
```
|
||
|
||
You may end up with a 4-byte gap between gpr3 and fp1 on architectures
|
||
that align values like this. The correct offset: value for fp1 is 12 -
|
||
in the g/G packet fp1 will immediately follow gpr3, even though the
|
||
in-memory thread structure has an empty 4 bytes for alignment between
|
||
these two registers.
|
||
|
||
The keys and values are detailed below:
|
||
|
||
* `name` -
|
||
The primary register name as a string ("rbp" for example)
|
||
* `alt-name` -
|
||
An alternate name for a register as a string ("fp" for example
|
||
for the above "rbp")
|
||
* `bitsize` - Size in bits of a register (32, 64, etc). Base 10.
|
||
* `offset` -
|
||
The offset within the "g" and "G" packet of the register data for
|
||
this register. This is the byte offset once the data has been
|
||
transformed into binary, not the character offset into the g/G
|
||
packet. Base 10.
|
||
* `encoding` -
|
||
The encoding type of the register which must be one of:
|
||
* `uint` (unsigned integer)
|
||
* `sint` (signed integer)
|
||
* `ieee754` (IEEE 754 float)
|
||
* `vector` (vector register)
|
||
* format -
|
||
The preferred format for display of this register. The value must be one of:
|
||
* `binary`
|
||
* `decimal`
|
||
* `hex`
|
||
* `float`
|
||
* `vector-sint8`
|
||
* `vector-uint8`
|
||
* `vector-sint16`
|
||
* `vector-uint16`
|
||
* `vector-sint32`
|
||
* `vector-uint32`
|
||
* `vector-float32`
|
||
* `vector-uint128`
|
||
* `set`-
|
||
The register set name as a string that this register belongs to.
|
||
* `gcc` -
|
||
The GCC compiler registers number for this register (used for
|
||
EH frame and other compiler information that is encoded in the
|
||
executable files). The supplied number will be decoded like a
|
||
string passed to strtoul() with a base of zero, so the number
|
||
can be decimal, or hex if it is prefixed with "0x".
|
||
|
||
**Note:** If the compiler doesn't have a register number for this
|
||
register, this key/value pair should be omitted.
|
||
* `dwarf` -
|
||
The DWARF register number for this register that is used for this
|
||
register in the debug information. The supplied number will be decoded
|
||
like a string passed to strtoul() with a base of zero, so the number
|
||
can be decimal, or hex if it is prefixed with "0x".
|
||
|
||
**Note:** If the compiler doesn't have a register number for this
|
||
register, this key/value pair should be omitted.
|
||
* `generic` -
|
||
If the register is a generic register that most CPUs have, classify
|
||
it correctly so the debugger knows. Valid values are one of:
|
||
* `pc` (a program counter register. for example `name=eip;` (i386),
|
||
`name=rip;` (x86_64), `name=r15;` (32 bit arm) would
|
||
include a `generic=pc;` key value pair)
|
||
* `sp` (a stack pointer register. for example `name=esp;` (i386),
|
||
`name=rsp;` (x86_64), `name=r13;` (32 bit arm) would
|
||
include a `generic=sp;` key value pair)
|
||
* `fp` (a frame pointer register. for example `name=ebp;` (i386),
|
||
`name=rbp;` (x86_64), `name=r7;` (32 bit arm with macosx
|
||
ABI) would include a `generic=fp;` key value pair)
|
||
* `ra` (a return address register. for example `name=lr;` (32 bit ARM)
|
||
would include a `generic=ra;` key value pair)
|
||
* `flags` (a CPU flags register. for example `name=eflags;` (i386),
|
||
`name=rflags;` (x86_64), `name=cpsr;` (32 bit ARM)
|
||
would include a `generic=flags;` key value pair)
|
||
* `arg1` - `arg8` (specified for registers that contain function
|
||
arguments when the argument fits into a register)
|
||
* `container-regs` -
|
||
The value for this key is a comma separated list of raw hex (optional
|
||
leading "0x") register numbers.
|
||
|
||
This specifies that this register is contained in other concrete
|
||
register values. For example "eax" is in the lower 32 bits of the
|
||
"rax" register value for x86_64, so "eax" could specify that it is
|
||
contained in "rax" by specifying the register number for "rax" (whose
|
||
register number is 0x00):
|
||
```
|
||
container-regs:00;
|
||
```
|
||
If a register is comprised of one or more registers, like "d0" is ARM
|
||
which is a 64 bit register, it might be made up of "s0" and "s1". If
|
||
the register number for "s0" is 0x20, and the register number of "s1"
|
||
is "0x21", the "container-regs" key/value pair would be:
|
||
```
|
||
container-regs:20,21;
|
||
```
|
||
This is handy for defining what GDB used to call "pseudo" registers.
|
||
These registers are never requested by LLDB via the register read
|
||
or write packets, the container registers will be requested on behalf
|
||
of this register.
|
||
* `invalidate-regs` -
|
||
The value for this key is a comma separated list of raw hex (optional
|
||
leading "0x") register numbers.
|
||
|
||
This specifies which register values should be invalidated when this
|
||
register is modified. For example if modifying "eax" would cause "rax",
|
||
"eax", "ax", "ah", and "al" to be modified where rax is 0x0, eax is 0x15,
|
||
ax is 0x25, ah is 0x35, and al is 0x39, the "invalidate-regs" key/value
|
||
pair would be:
|
||
```
|
||
invalidate-regs:0,15,25,35,39;
|
||
```
|
||
If there is a single register that gets invalidated, then omit the comma
|
||
and just list a single register:
|
||
```
|
||
invalidate-regs:0;
|
||
```
|
||
This is handy when modifying a specific register can cause other
|
||
register values to change. For example, when debugging an ARM target,
|
||
modifying the CPSR register can cause the r8 - r14 and cpsr value to
|
||
change depending on if the mode has changed.
|
||
|
||
**Priority To Implement:** High. Any target that can self describe its registers,
|
||
should do so. This means if new registers are ever added to a remote target, they
|
||
will get picked up automatically, and allows registers to change
|
||
depending on the actual CPU type that is used.
|
||
|
||
**Note:** `qRegisterInfo` is deprecated in favor of the standard gdb remote
|
||
serial protocol register description method, `qXfer:features:read:target.xml`.
|
||
If `qXfer:features:read:target.xml` is supported, `qRegisterInfo` does
|
||
not need to be implemented. The target.xml format is used by most
|
||
gdb RSP stubs whereas `qRegisterInfo` was an lldb-only design.
|
||
`qRegisterInfo` requires one packet per register and can have undesirable
|
||
performance costs at the start of a debug session, whereas target.xml
|
||
may be able to describe all registers in a single packet.
|
||
|
||
## qShlibInfoAddr
|
||
|
||
Get an address where the dynamic linker stores information about
|
||
where shared libraries are loaded.
|
||
|
||
LLDB and GDB both support the `qShlibInfoAddr` packet which is a hint to each
|
||
debugger as to where to find the dynamic loader information. For darwin
|
||
binaries that run in user land this is the address of the `all_image_infos`
|
||
structure in the `/usr/lib/dyld` executable, or the result of a `TASK_DYLD_INFO`
|
||
call. The result is returned as big endian hex bytes that are the address
|
||
value:
|
||
```
|
||
send packet: $qShlibInfoAddr#00
|
||
read packet: $7fff5fc40040#00
|
||
```
|
||
|
||
**Priority To Implement:** High
|
||
|
||
If you have a dynamic loader plug-in in LLDB for your target
|
||
triple (see the "qHostInfo" packet) that can use this information.
|
||
Many times address load randomization can make it hard to detect
|
||
where the dynamic loader binary and data structures are located and
|
||
some platforms know, or can find out where this information is.
|
||
|
||
Low if you have a debug target where all object and symbol files
|
||
contain static load addresses.
|
||
|
||
## qSpeedTest
|
||
|
||
Test the maximum speed at which packets can be sent and received.
|
||
|
||
```
|
||
send packet: qSpeedTest:response_size:<response size>;
|
||
read packet: data:<response data>
|
||
```
|
||
|
||
`<response size>` is a hex encoded unsigned number up to 64 bits in size.
|
||
The remote will respond with `data:` followed by a block of `a` characters
|
||
whose size should match `<response size>`, if the connection is stable.
|
||
|
||
If there is an error parsing the packet, the response is `E79`.
|
||
|
||
This packet is used by LLDB to discover how reliable the connection is by
|
||
varying the amount of data requested by `<response size>` and checking whether
|
||
the expected amount and values were received.
|
||
|
||
**Priority to Implemment:** Not required for debugging on the same host, otherwise
|
||
low unless you know your connection quality is variable.
|
||
|
||
## qSymbol
|
||
|
||
Notify the remote that LLDB is ready to do symbol lookups on behalf of the
|
||
debug server. The response is the symbol name the debug server wants to know the
|
||
value of, or `OK` if the debug server does not need to know any more symbol values.
|
||
|
||
The exchange always begins with:
|
||
```
|
||
send packet: qSymbol::
|
||
```
|
||
|
||
The `::` are delimiters for fields that may be filled in future responses. These
|
||
delimiters must be included even in the first packet sent.
|
||
|
||
The debug server can reply one of two ways. If it doesn't need any symbol values:
|
||
```
|
||
read packet: OK
|
||
```
|
||
|
||
If it does need a symbol value, it includes the ASCII hex encoded name of the
|
||
symbol:
|
||
```
|
||
read packet: qSymbol:6578616D706C65
|
||
```
|
||
|
||
This should be looked up by LLDB then sent back to the server. Include the name
|
||
again, with the vaue as a hex number:
|
||
```
|
||
read packet: qSymbol:6578616D706C65:CAFEF00D
|
||
```
|
||
|
||
If LLDB cannot find the value, it should respond with only the name. Note that
|
||
the second `:` is not included here, whereas it is in the initial packet.
|
||
```
|
||
read packet: qSymbol:6578616D706C65
|
||
```
|
||
|
||
If LLDB is asked for any symbols that it cannot find, it should send the
|
||
initial `qSymbol::` again at any point where new libraries are loaded. In case
|
||
the symbol can now be resolved.
|
||
|
||
If the debug server has requested all the symbols it wants, the final response
|
||
will be `OK` (whether they were all found or not).
|
||
|
||
If LLDB did find all the symbols and receives an `OK` it does not need to send
|
||
`qSymbol::` again during the debug session.
|
||
|
||
**Priority To Implement:** Low, this is rarely used.
|
||
|
||
## qThreadStopInfo\<tid\>
|
||
|
||
Get information about why a thread, whose ID is `<tid>`, is stopped.
|
||
|
||
LLDB tries to use the `qThreadStopInfo` packet which is formatted as
|
||
`qThreadStopInfo%x` where `%x` is the hex thread ID. This requests information
|
||
about why a thread is stopped. The response is the same as the stop reply
|
||
packets and tells us what happened to the other threads. The standard GDB
|
||
remote packets love to think that there is only _one_ reason that _one_ thread
|
||
stops at a time. This allows us to see why all threads stopped and allows us
|
||
to implement better multi-threaded debugging support.
|
||
|
||
**Priority To Implement:** High
|
||
|
||
If you need to support multi-threaded or multi-core debugging.
|
||
Many times one thread will hit a breakpoint and while the debugger
|
||
is in the process of suspending the other threads, other threads
|
||
will also hit a breakpoint. This packet allows LLDB to know why all
|
||
threads (live system debug) / cores (JTAG) in your program have
|
||
stopped and allows LLDB to display and control your program
|
||
correctly.
|
||
|
||
## qWatchpointSupportInfo
|
||
|
||
Get the number of hardware watchpoints available on the remote target.
|
||
|
||
```
|
||
send packet: $qWatchpointSupportInfo:#55
|
||
read packet: $num:4;#f9
|
||
```
|
||
|
||
`num` is the number of hardware breakpoints, it will be `0` if none are
|
||
available.
|
||
|
||
**Priority to Implement:** Low. If this packet is not supported, LLDB will assume
|
||
that hardware breakpoints are supported. If that is not the case, LLDB assumes
|
||
that the debug stub will respond with an error when asked to set a hardware
|
||
watchpoint.
|
||
|
||
## Stop reply packet extensions
|
||
|
||
This section describes some of the additional information you can
|
||
specify in stop reply packets that help LLDB to know more detailed
|
||
information about your threads.
|
||
|
||
Standard GDB remote stop reply packets are reply packets sent in
|
||
response to a packet that made the program run. They come in the
|
||
following forms:
|
||
|
||
* `SAA` -
|
||
`S` means signal and `AA` is a hex signal number that describes why
|
||
the thread or stopped. It doesn't specify which thread, so the `T`
|
||
packet is recommended to use instead of the `S` packet.
|
||
|
||
* `TAAkey1:value1;key2:value2;...` -
|
||
`T` means a thread stopped due to a unix signal where `AA` is a hex
|
||
signal number that describes why the program stopped. This is
|
||
followed by a series of key/value pairs:
|
||
* If key is a hex number, it is a register number and value is
|
||
the hex value of the register in debuggee endian byte order.
|
||
An empty value indicates that the register cannot be fetched
|
||
at this stop point; lldb will not succeed if it sends a separate
|
||
read-register packet.
|
||
* If key == "thread", then the value is the big endian hex
|
||
thread-id of the stopped thread.
|
||
* If key == "core", then value is a hex number of the core on
|
||
which the stop was detected.
|
||
* If key == "watch" or key == "rwatch" or key == "awatch", then
|
||
value is the data address in big endian hex
|
||
* If key == "library", then value is ignored and `qXfer:libraries:read`
|
||
packets should be used to detect any newly loaded shared libraries.
|
||
The server emits this whenever one or more shared libraries have been
|
||
loaded or unloaded since the last stop. On Linux/SVR4 systems
|
||
lldb-server does not emit `library:`, since the dynamic loader is
|
||
observable via a breakpoint on `_dl_debug_state`. Instead, the BP hit
|
||
serves as the notification (and clients use `qXfer:libraries-svr4:read`).
|
||
On Windows, where the kernel raises `LOAD_DLL_DEBUG_EVENT` /
|
||
`UNLOAD_DLL_DEBUG_EVENT` directly, lldb-server tracks pending events via
|
||
`NativeProcessProtocol::HasPendingLibraryEvents()` and emits `library:1;`
|
||
in the next stop reply.
|
||
|
||
* `WAA` - `W` means the process exited and `AA` is the exit status.
|
||
|
||
* `XAA` - `X` means the process exited and `AA` is signal that caused the program
|
||
to exit.
|
||
|
||
* `O<ascii-hex-string>` - `O` means `STDOUT` has data that was written to its
|
||
console and is being delivered to the debugger. This packet happens asynchronously
|
||
and the debugger is expected to continue to wait for another stop reply
|
||
packet.
|
||
|
||
### Lldb Extensions
|
||
|
||
We have extended the `T` packet to be able to also understand the
|
||
following keys and values:
|
||
|
||
* `metype` - `unsigned` -
|
||
mach exception type (the value of the `EXC_XXX` enumerations)
|
||
as an unsigned integer. For targets with mach
|
||
kernels only.
|
||
* `mecount` - `unsigned` -
|
||
mach exception data count as an unsigned integer
|
||
For targets with mach kernels only.
|
||
* `medata` - `unsigned` -
|
||
There should be `mecount` of these and it is the data
|
||
that goes along with a mach exception (as an unsigned
|
||
integer). For targets with mach kernels only.
|
||
* `name` - `string` -
|
||
The name of the thread as a plain string. The string
|
||
must not contain an special packet characters or
|
||
contain a `:` or a `;`. Use `hexname` if the thread
|
||
name has special characters.
|
||
* `hexname` - `ascii-hex` - An ASCII hex string that contains the name of the thread
|
||
* `qaddr` - `hex` -
|
||
Big endian hex value that contains the `libdispatch`
|
||
queue address for the queue of the thread.
|
||
* `reason` - `enum` - The enumeration must be one of:
|
||
* `trace` -
|
||
the program stopped after a single instruction
|
||
was executed on a core. Usually done when single
|
||
stepping past a breakpoint
|
||
* `breakpoint` - a breakpoint set using a `z` packet was hit.
|
||
* `trap` - stopped due to user interruption
|
||
* `signal` -
|
||
stopped due to an actual unix signal, not
|
||
just the debugger using a unix signal to keep
|
||
the GDB remote client happy.
|
||
* `watchpoint` - Can be used with of the `watch`/`rwatch`/`awatch` key value
|
||
pairs. Or can be used *instead* of those keys, with the specially formatted
|
||
`description` field.
|
||
* `exception` - an exception stop reason. Use with
|
||
the `description` key/value pair to describe the
|
||
exceptional event the user should see as the stop
|
||
reason.
|
||
* `description` -
|
||
An ASCII hex string that contains a more descriptive
|
||
reason that the thread stopped. This is only needed
|
||
if none of the key/value pairs are enough to
|
||
describe why something stopped.
|
||
|
||
For `reason:watchpoint`, `description` is an ascii-hex
|
||
encoded string with between one and three base 10 numbers,
|
||
space separated. The three numbers are:
|
||
1. Watchpoint address. This address should always be within
|
||
a memory region lldb has a watchpoint on.
|
||
On architectures where the actual reported hit address may
|
||
be outside the watchpoint that was triggered, the remote
|
||
stub should determine which watchpoint was triggered and
|
||
report an address from within its range.
|
||
2. Watchpoint hardware register index number.
|
||
3. Actual watchpoint trap address, which may be outside
|
||
the range of any watched region of memory. On MIPS, an addr
|
||
outside a watched range means lldb should disable the wp,
|
||
step, re-enable the wp and continue silently.
|
||
|
||
On MIPS, the low 3 bits are masked so if a watchpoint is on
|
||
0x1004, a 2-byte write to 0x1000 will trigger the watchpoint
|
||
(a false positive hit), and lldb needs to disable the
|
||
watchpoint at 0x1004, inst-step, then re-enable the watchpoint
|
||
and not make this a user visible event. The description here
|
||
would be "0x1004 0 0x1000". lldb needs a known watchpoint address
|
||
in the first field, so it can disable it and step.
|
||
|
||
On AArch64 we have a related issue, where you watch 4 bytes at
|
||
0x1004, an instruction does an 8-byte write starting at
|
||
0x1000 (a true watchpoint hit) and the hardware may report the
|
||
trap address as 0x1000 - before the watched memory region -
|
||
with the write extending into the watched region. This can
|
||
be reported as "0x1004 0 0x1000". lldb will use 0x1004 to
|
||
identify which Watchpoint was triggered, and can report 0x1000
|
||
to the user. The behavior of silently stepping over the
|
||
watchpoint, with an 3rd field addr outside the range, is
|
||
restricted to MIPS.
|
||
|
||
There may be false-positive watchpoint hits on AArch64 as well,
|
||
in the SVE Streaming Mode, but that is less common (see ESR
|
||
register flag "WPF", "Watchpoint might be False-Positive") and
|
||
not currently handled by lldb.
|
||
* `threads` - `comma-sep-base16` -
|
||
A list of thread ids for all threads (including
|
||
the thread that we're reporting as stopped) that
|
||
are live in the process right now. lldb may
|
||
request that this be included in the T packet via
|
||
the QListThreadsInStopReply packet earlier in
|
||
the debug session.
|
||
|
||
Example:
|
||
```
|
||
threads:63387,633b2,63424,63462,63486;
|
||
```
|
||
* `thread-pcs` - `comma-sep-base16` -
|
||
A list of pc values for all threads that currently
|
||
exist in the process, including the thread that
|
||
this `T` packet is reporting as stopped.
|
||
This key-value pair will only be emitted when the
|
||
`threads` key is already included in the `T` packet.
|
||
The pc values correspond to the threads reported
|
||
in the `threads` list. The number of pcs in the
|
||
`thread-pcs` list will be the same as the number of
|
||
threads in the `threads` list.
|
||
lldb may request that this be included in the `T`
|
||
packet via the `QListThreadsInStopReply` packet
|
||
earlier in the debug session.
|
||
|
||
Example:
|
||
```
|
||
thread-pcs:dec14,2cf872b0,2cf8681c,2d02d68c,2cf716a8;
|
||
```
|
||
* `addressing_bits` - `unsigned` (optional) -
|
||
Specifies how many bits in addresses are significant for addressing, base
|
||
10. If bits 38..0 in a 64-bit pointer are significant for addressing, then the
|
||
value is 39. This is needed on e.g. AArch64 v8.3 ABIs that use pointer
|
||
authentication in the high bits. This value is normally sent in the `qHostInfo`
|
||
packet response, and if the value cannot change during the process lifetime,
|
||
it does not need to be duplicated here in the stop packet. For a firmware
|
||
environment with early start code that may be changing the page table setup,
|
||
a dynamically set value may be needed.
|
||
* `low_mem_addressing_bits` - `unsigned` (optional) -
|
||
Specifies how many bits in addresses in low memory are significant for
|
||
addressing, base 10. AArch64 can have different page table setups for low
|
||
and high memory, and therefore a different number of bits used for addressing.
|
||
* `high_mem_addressing_bits` - `unsigned` (optional) -
|
||
Specifies how many bits in addresses in high memory are significant for
|
||
addressing, base 10. AArch64 can have different page table setups for low and
|
||
high memory, and therefore a different number of bits used for addressing.
|
||
* `added-binaries` when the remote stub knows that a thread has stopped
|
||
at a binaries-loaded breakpoint notification, and it can retrieve the list
|
||
of binaries that have just been loaded, it may send the list of base16
|
||
addresses (no 0x prefix) for all of the binaries, to save lldb the need
|
||
to read it from memory.
|
||
* `detailed-binaries-info` when the remote stub knows that a thread
|
||
has stopped at a binaries-loaded breakpoint notification, it may
|
||
be able to gather detailed information about the newly loaded
|
||
binaries, the information jGetLoadedDynamicLibrariesInfos would
|
||
return. If this key is present, the information for all binaries
|
||
being added at this stop are provided. The value is asciihex
|
||
encoded JSON. It must be asciihex encoded in case a filename
|
||
includes one of the gdb RSP packet metacharacters or a semicolon.
|
||
|
||
### Best Practices
|
||
|
||
Since register values can be supplied with this packet, it is often useful
|
||
to return the PC, SP, FP, LR (if any), and FLAGS registers so that separate
|
||
packets don't need to be sent to read each of these registers from each
|
||
thread.
|
||
|
||
If a thread is stopped for no reason (like just because another thread
|
||
stopped, or because when one core stops all cores should stop), use a
|
||
`T` packet with `00` as the signal number and fill in as many key values
|
||
and registers as possible.
|
||
|
||
LLDB likes to know why a thread stopped since many thread control
|
||
operations like stepping over a source line, actually are implemented
|
||
by running the process multiple times. If a breakpoint is hit while
|
||
trying to step over a source line and LLDB finds out that a breakpoint
|
||
is hit in the "reason", we will know to stop trying to do the step
|
||
over because something happened that should stop us from trying to
|
||
do the step. If we are at a breakpoint and we disable the breakpoint
|
||
at the current PC and do an instruction single step, knowing that
|
||
we stopped due to a "trace" helps us know that we can continue
|
||
running versus stopping due to a "breakpoint" (if we have two
|
||
breakpoint instruction on consecutive instructions). So the more info
|
||
we can get about the reason a thread stops, the better job LLDB can
|
||
do when controlling your process. A typical GDB server behavior is
|
||
to send a SIGTRAP for breakpoints _and_ also when instruction single
|
||
stepping, in this case the debugger doesn't really know why we
|
||
stopped and it can make it hard for the debugger to control your
|
||
program correctly. What if a real SIGTRAP was delivered to a thread
|
||
while we were trying to single step? We wouldn't know the difference
|
||
with a standard GDB remote server and we could do the wrong thing.
|
||
|
||
**Priority To Implement:** High. Having the extra information in your stop reply
|
||
packets makes your debug session more reliable and informative.
|
||
|
||
## vAttachName
|
||
|
||
Same as `vAttach`, except instead of a `pid` you send a process name.
|
||
|
||
**Priority To Implement:** Low. Only needed for `process attach -n`. If the
|
||
packet isn't supported then `process attach -n` will fail gracefully. So you need
|
||
only to support it if attaching to a process by name makes sense for your environment.
|
||
|
||
## vAttachOrWait
|
||
|
||
Same as `vAttachWait`, except that the stub will attach to a process
|
||
by name if it exists, and if it does not, it will wait for a process
|
||
of that name to appear and attach to it.
|
||
|
||
**Priority To Implement:** Low
|
||
|
||
Only needed to implement `process attach -w -i false -n`. If
|
||
you don't implement it but do implement `-n` AND lldb can somehow get
|
||
a process list from your device, it will fall back on scanning the
|
||
process list, and sending `vAttach` or `vAttachWait` depending on
|
||
whether the requested process exists already. This is racy,
|
||
however, so if you want to support this behavior it is better to
|
||
support this packet.
|
||
|
||
## vAttachWait
|
||
|
||
Same as `vAttachName`, except that the stub should wait for the next instance
|
||
of a process by that name to be launched and attach to that.
|
||
|
||
**Priority To Implement:** Low. Only needed to support `process attach -w -n`
|
||
which will fail gracefully if the packet is not supported.
|
||
|
||
## vFile Packets
|
||
|
||
Though some of these may match the ones described in GDB's protocol
|
||
documentation, we include our own expectations here in case of
|
||
mismatches or extensions.
|
||
|
||
### vFile:chmod / qPlatform_chmod
|
||
|
||
Change the permissions of a file on the connected remote machine.
|
||
|
||
Request: `qPlatform_chmod:<hex-file-mode>,<ascii-hex-path>`
|
||
|
||
Reply:
|
||
* `F<chmod-return-code>`
|
||
(chmod called successfully and returned with the given return code)
|
||
* `Exx` (An error occurred)
|
||
|
||
### vFile:close
|
||
|
||
Close a previously opened file descriptor.
|
||
|
||
```
|
||
receive: vFile:close:7
|
||
send: F0
|
||
```
|
||
|
||
File descriptor is in base 16. `F-1,errno` with the errno if an error occurs,
|
||
errno is base 16.
|
||
|
||
### vFile:exists
|
||
|
||
Check whether the file at the given path exists.
|
||
|
||
```
|
||
receive: vFile:exists:2f746d702f61
|
||
send (exists): F,1
|
||
send (does not exist): F,0
|
||
```
|
||
|
||
Request packet contains the ASCII hex encoded filename.
|
||
|
||
The response is a return code where 1 means the file exists
|
||
and 0 means it does not.
|
||
|
||
**Priority To Implement:** Low
|
||
|
||
### vFile:MD5
|
||
|
||
Generate an MD5 hash of the file at the given path.
|
||
|
||
```
|
||
receive: vFile:MD5:2f746d702f61
|
||
send (success): F,00000000000000001111111111111111
|
||
send (failure): F,x
|
||
```
|
||
|
||
Request packet contains the ASCII hex encoded filename.
|
||
|
||
If the hash succeeded, the response is `F,` followed by the low 64
|
||
bits of the result, and finally the high 64 bits of the result. Both are in
|
||
hex format without a prefix.
|
||
|
||
The response is `F,`, followed by `x` if the file did not exist
|
||
or failed to hash.
|
||
|
||
### vFile:mode
|
||
|
||
Get the mode bits of a file on the target system, filename in ASCII hex.
|
||
|
||
```
|
||
receive: vFile:mode:2f746d702f61
|
||
send: F1ed
|
||
```
|
||
|
||
response is `F` followed by the mode bits in base 16, this `0x1ed` would
|
||
correspond to `0755` in octal.
|
||
`F-1,errno` with the errno if an error occurs, base 16.
|
||
|
||
### vFile:open
|
||
|
||
Open a file on the remote system and return the file descriptor of it.
|
||
|
||
```
|
||
receive: vFile:open:2f746d702f61,00000001,00000180
|
||
send: F8
|
||
```
|
||
|
||
request packet has the fields:
|
||
1. ASCII hex encoded filename
|
||
2. Flags passed to the open call, base 16.
|
||
Note that these are not the `oflags` that `open(2)` takes, but
|
||
are the constant values in `enum OpenOptions` from LLDB's
|
||
[`File.h`](https://github.com/llvm/llvm-project/blob/main/lldb/include/lldb/Host/File.h).
|
||
3. Mode bits, base 16
|
||
|
||
response is `F` followed by the opened file descriptor in base 16.
|
||
`F-1,errno` with the errno if an error occurs, base 16.
|
||
|
||
### vFile:pread
|
||
|
||
Read data from an opened file descriptor.
|
||
|
||
```
|
||
receive: vFile:pread:7,1024,0
|
||
send: F4;a'b\00
|
||
```
|
||
|
||
Request packet has the fields:
|
||
1. File descriptor, base 16
|
||
2. Number of bytes to be read, base 16
|
||
3. Offset into file to start from, base 16
|
||
|
||
Response is `F`, followed by the number of bytes read (base 16), a
|
||
semicolon, followed by the data in the binary-escaped-data encoding.
|
||
|
||
### vFile:pwrite
|
||
|
||
Write data to a previously opened file descriptor.
|
||
|
||
```
|
||
receive: vFile:pwrite:8,0,\cf\fa\ed\fe\0c\00\00
|
||
send: F1024
|
||
```
|
||
|
||
Request packet has the fields:
|
||
1. File descriptor, base 16
|
||
2. Offset into file to start from, base 16
|
||
3. binary-escaped-data to be written
|
||
|
||
Response is `F`, followed by the number of bytes written (base 16).
|
||
|
||
### vFile:size
|
||
|
||
Get the size of a file on the target system, filename in ASCII hex.
|
||
|
||
```
|
||
receive: vFile:size:2f746d702f61
|
||
send: Fc008
|
||
```
|
||
|
||
response is `F` followed by the file size in base 16.
|
||
`F-1,errno` with the errno if an error occurs, base 16.
|
||
|
||
### vFile:symlink
|
||
|
||
Create a symbolic link (symlink, soft-link) on the target system.
|
||
|
||
```
|
||
receive: vFile:symlink:<SRC-FILE>,<DST-NAME>
|
||
send: F0,0
|
||
```
|
||
|
||
Argument file paths are in ascii-hex encoding.
|
||
Response is `F` plus the return value of `symlink()`, base 16 encoding,
|
||
optionally followed by the value of errno if it failed, also base 16.
|
||
|
||
### vFile:unlink
|
||
|
||
Remove a file on the target system.
|
||
|
||
```
|
||
receive: vFile:unlink:2f746d702f61
|
||
send: F0
|
||
```
|
||
|
||
Argument is a file path in ascii-hex encoding.
|
||
Response is `F` plus the return value of `unlink()`, base 16 encoding.
|
||
Return value may optionally be followed by a comma and the base16
|
||
value of errno if unlink failed.
|
||
|
||
## Wasm Packets
|
||
|
||
The packet below are supported by the
|
||
[WAMR](https://github.com/bytecodealliance/wasm-micro-runtime) and
|
||
[V8](https://v8.dev) Wasm runtimes.
|
||
|
||
|
||
### qWasmCallStack
|
||
|
||
Get the Wasm call stack for the given thread id. This returns a hex-encoded
|
||
list (with no delimiters) of 64-bit PC values, one for each frame of the call
|
||
stack. To match the Wasm specification, the addresses are encoded in little
|
||
endian byte order, even if the endian of the Wasm runtime's host is not little
|
||
endian.
|
||
|
||
```
|
||
send packet: $qWasmCallStack:202dbe040#08
|
||
read packet: $9c01000000000040e501000000000040fe01000000000040#
|
||
```
|
||
|
||
**Priority to Implement:** Only required for Wasm support. Necessary to show
|
||
stack traces.
|
||
|
||
### qWasmGlobal
|
||
|
||
Get the value of a Wasm global variable for the given frame index at the given
|
||
variable index. The indexes are encoded as base 10. The result is a hex-encoded
|
||
little-endian value of the global.
|
||
|
||
```
|
||
send packet: $qWasmGlobal:0;2#cb
|
||
read packet: $e0030100#b9
|
||
```
|
||
|
||
**Priority to Implement:** Only required for Wasm support. Necessary to show
|
||
variables.
|
||
|
||
|
||
### qWasmLocal
|
||
|
||
Get the value of a Wasm function argument or local variable for the given frame
|
||
index at the given variable index. The indexes are encoded as base 10. The
|
||
result is a hex-encoded little-endian value of the local.
|
||
|
||
|
||
```
|
||
send packet: $qWasmLocal:0;2#cb
|
||
read packet: $e0030100#b9
|
||
```
|
||
|
||
**Priority to Implement:** Only required for Wasm support. Necessary to show
|
||
variables.
|
||
|
||
|
||
### qWasmStackValue
|
||
|
||
Get the value of a Wasm local variable from the Wasm operand stack, for the
|
||
given frame index at the given variable index. The indexes are encoded as base
|
||
10. The result is a hex-encoded little-endian value from the stack at the given index.
|
||
|
||
```
|
||
send packet: $qWasmStackValue:0;2#cb
|
||
read packet: $e0030100#b9
|
||
```
|
||
|
||
**Priority to Implement:** Only required for Wasm support. Necessary to show
|
||
variables.
|
||
|
||
## "x" - Binary memory read
|
||
|
||
> **Warning:** The format of this packet was decided before GDB 16
|
||
> introduced its own format for `x`. Future versions of LLDB may not
|
||
> support the format described here, and new code should produce and
|
||
> expect the format used by GDB.
|
||
|
||
Like the `m` (read) and `M` (write) packets, this is a partner to the
|
||
`X` (write binary data) packet, `x`.
|
||
|
||
It is called like
|
||
```
|
||
xADDRESS,LENGTH
|
||
```
|
||
|
||
where both `ADDRESS` and `LENGTH` are big-endian base 16 values.
|
||
|
||
To test if this packet is available, send a addr/len of 0:
|
||
```
|
||
x0,0
|
||
```
|
||
You will get an `OK` response if it is supported.
|
||
|
||
The reply will be the data requested in 8-bit binary data format.
|
||
The standard quoting is applied to the payload. Characters `} # $ *`
|
||
will all be escaped with `}` (`0x7d`) character and then XOR'ed with `0x20`.
|
||
|
||
A typical use to read 512 bytes at 0x1000 would look like:
|
||
```
|
||
x0x1000,0x200
|
||
```
|
||
The `0x` prefixes are optional - like most of the gdb-remote packets,
|
||
omitting them will work fine; these numbers are always base 16.
|
||
|
||
The length of the payload is not provided. A reliable, 8-bit clean,
|
||
transport layer is assumed.
|
||
|
||
## Accelerator Packets
|
||
|
||
The packets below support debugging hardware accelerators (e.g. GPUs,
|
||
FPGAs) alongside the native host process via accelerator plugins installed
|
||
in lldb-server.
|
||
|
||
### jAcceleratorPluginInitialize
|
||
|
||
This packet requests initialization data from all accelerator plugins
|
||
installed in lldb-server. Accelerator plugins allow lldb-server to support
|
||
debugging of hardware accelerators (e.g. GPUs, FPGAs) alongside the native
|
||
host process.
|
||
|
||
This packet requires the `accelerator-plugins+` feature from `qSupported`.
|
||
It should be sent early in the session, after `qSupported` but before
|
||
launching or attaching to an inferior process. If the hardware accelerator
|
||
is not present, launching or attaching to the accelerator debug session
|
||
will fail.
|
||
|
||
```
|
||
LLDB SENDS: jAcceleratorPluginInitialize
|
||
STUB REPLIES: [<accelerator_action>,...]
|
||
```
|
||
|
||
Each `accelerator_action` is a JSON object with the following required fields:
|
||
|
||
| Key | Type | Description |
|
||
|----------------|---------|-------------|
|
||
| `plugin_name` | string | Unique name identifying the accelerator plugin (e.g. `"mock"`, `"amdgpu"`). Each installed plugin has a globally unique name. |
|
||
| `session_name` | string | Human-readable label for the accelerator target, stored on the Target object to distinguish it from the CPU target (e.g. `"AMD GPU Session"`). May be empty. |
|
||
| `identifier` | integer | Identifier for this action, unique within the scope of its `plugin_name`. To refer to a specific action, use the combination of `plugin_name` and `identifier`. |
|
||
|
||
There can be multiple accelerator plugins installed, each with a globally
|
||
unique `plugin_name`. The response is a JSON array with one entry per
|
||
installed plugin.
|
||
|
||
Example:
|
||
```
|
||
LLDB SENDS: jAcceleratorPluginInitialize
|
||
STUB REPLIES: [{"plugin_name":"amdgpu","session_name":"AMD GPU Session","identifier":0}]
|
||
```
|
||
|
||
If no accelerator plugins are installed, the server does not advertise the
|
||
`accelerator-plugins+` feature and this packet should not be sent.
|
||
|
||
Each `accelerator_action` may include a `breakpoints` array requesting
|
||
breakpoints to be set in the native process. See
|
||
`jAcceleratorPluginBreakpointHit` for the callback when those breakpoints
|
||
are hit.
|
||
|
||
In future patches, each `accelerator_action` will include additional fields
|
||
such as connection info for secondary debug sessions and synchronization
|
||
options.
|
||
|
||
**Priority To Implement:** Required for hardware accelerator debugging
|
||
support. Not needed for non-hardware-accelerator debugging.
|
||
|
||
### jAcceleratorPluginBreakpointHit
|
||
|
||
Sent by the client when a breakpoint requested by an accelerator plugin
|
||
is hit in the native process. This packet requires the
|
||
`accelerator-plugins+` feature from `qSupported`.
|
||
|
||
```
|
||
LLDB SENDS: jAcceleratorPluginBreakpointHit:<json>
|
||
STUB REPLIES: <json_response>
|
||
```
|
||
|
||
The request JSON has the following fields:
|
||
|
||
| Key | Type | Description |
|
||
|-----------------|--------|-------------|
|
||
| `plugin_name` | string | Name of the plugin that requested the breakpoint. |
|
||
| `breakpoint` | object | The `AcceleratorBreakpointInfo` that was hit, including its `identifier`. |
|
||
| `symbol_values` | array | Array of `{"name": "<name>", "value": <addr>}` for each symbol requested in the breakpoint's `symbol_names`. |
|
||
|
||
The response JSON has the following fields:
|
||
|
||
| Key | Type | Description |
|
||
|----------------------|------|-------------|
|
||
| `disable_bp` | bool | If true, the client should disable this breakpoint. |
|
||
| `auto_resume_native` | bool | If true, the native process should automatically resume after handling the hit. |
|
||
| `actions` | object | Optional `AcceleratorActions` for the client to perform. |
|
||
|
||
Example:
|
||
```
|
||
LLDB SENDS: jAcceleratorPluginBreakpointHit:{"plugin_name":"mock","breakpoint":{"identifier":1,"symbol_names":[]},"symbol_values":[]}
|
||
STUB REPLIES: {"disable_bp":true,"auto_resume_native":false,"actions":{"plugin_name":"mock","session_name":"","identifier":2,"breakpoints":[{"identifier":2,"by_name":{"function_name":"exit"},"symbol_names":[]}]}}
|
||
```
|
||
|
||
**Priority To Implement:** Required for hardware accelerator debugging
|
||
support. Not needed for non-hardware-accelerator debugging.
|