| LLDB has added new GDB server packets to better support multi-threaded and |
| remote debugging. Why? 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. Below are the details on the new packets we have |
| added above and beyond the standard GDB remote protocol packets. |
| |
| //---------------------------------------------------------------------- |
| // "QStartNoAckMode" |
| // |
| // BRIEF |
| // Try to enable no ACK mode to skip sending ACKs and NACKs. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| 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: + |
| |
| |
| |
| //---------------------------------------------------------------------- |
| // "A" - launch args packet |
| // |
| // BRIEF |
| // Launch a program using the supplied arguments |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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 foreach 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. |
| |
| //---------------------------------------------------------------------- |
| // "QEnvironment:NAME=VALUE" |
| // |
| // BRIEF |
| // 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. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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. |
| |
| //---------------------------------------------------------------------- |
| // "QEnvironmentHexEncoded:HEX-ENCODING(NAME=VALUE)" |
| // |
| // BRIEF |
| // 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. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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. |
| |
| //---------------------------------------------------------------------- |
| // "QEnableErrorStrings" |
| // |
| // BRIEF |
| // 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. 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. |
| //---------------------------------------------------------------------- |
| |
| send packet: $QEnableErrorStrings |
| read packet: $OK#00 |
| |
| //---------------------------------------------------------------------- |
| // "QSetSTDIN:<ascii-hex-path>" |
| // "QSetSTDOUT:<ascii-hex-path>" |
| // "QSetSTDERR:<ascii-hex-path>" |
| // |
| // BRIEF |
| // Setup where STDIN, STDOUT, and STDERR go prior to sending an "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. |
| //---------------------------------------------------------------------- |
| |
| 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. |
| |
| //---------------------------------------------------------------------- |
| // "QSetWorkingDir:<ascii-hex-path>" |
| // |
| // BRIEF |
| // Set the working directory prior to sending an "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. |
| //---------------------------------------------------------------------- |
| |
| Or specify the working directory: |
| |
| QSetWorkingDir:<ascii-hex-path> |
| |
| This packet must be sent _prior_ to sending a "A" packet. |
| |
| //---------------------------------------------------------------------- |
| // "QSetDisableASLR:<bool>" |
| // |
| // BRIEF |
| // Enable or disable ASLR on the next "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). |
| //---------------------------------------------------------------------- |
| |
| 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. |
| |
| //---------------------------------------------------------------------- |
| // QListThreadsInStopReply |
| // |
| // BRIEF |
| // 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. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| send packet: QListThreadsInStopReply |
| read packet: OK |
| |
| //---------------------------------------------------------------------- |
| // jLLDBTraceSupported |
| // |
| // BRIEF |
| // 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. |
| // |
| // OUTPUT SCHEMA |
| // { |
| // "name": <string>, |
| // Tracing technology name, e.g. intel-pt, arm-coresight. |
| // "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. |
| //---------------------------------------------------------------------- |
| |
| send packet: jLLDBTraceSupported |
| read packet: {"name":<name>, "description":<description>}/E<error code>;AAAAAAAAA |
| |
| //---------------------------------------------------------------------- |
| // jLLDBTraceStart |
| // |
| // BRIEF |
| // 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. |
| // |
| // THREAD TRACING |
| // This traces specific threads. |
| // |
| // INPUT SCHEMA |
| // { |
| // "type": <string>, |
| // Tracing technology name, e.g. intel-pt, arm-coresight. |
| // |
| // /* 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 by tracing each thread individually, but |
| // managed by the same "process trace" instance. |
| // Each actual thread trace, 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: |
| // { |
| // "threadBufferSize": <decimal integer>, |
| // Trace buffer size per thread in bytes. 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 */ |
| // "processBufferSizeLimit": <decimal integer>, |
| // Maximum total buffer size per process in bytes. |
| // This limit applies to the sum of the sizes of all trace buffers for |
| // the current process, excluding the ones started with "thread tracing". |
| // |
| // 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. |
| // } |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| Process tracing: |
| send packet: jLLDBTraceStart:{"type":<type>,...other params}] |
| read packet: OK/E<error code>;AAAAAAAAA |
| |
| Thread tracing: |
| send packet: jLLDBTraceStart:{"type":<type>,"tids":<tids>,...other params}] |
| read packet: OK/E<error code>;AAAAAAAAA |
| |
| //---------------------------------------------------------------------- |
| // jLLDBTraceStop |
| // |
| // BRIEF |
| // 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". |
| // |
| // THREAD TRACE STOPPING |
| // This is a best effort request, which tries to stop as many traces as |
| // possible. |
| // |
| // INPUT SCHEMA |
| // The schema for the input is |
| // |
| // { |
| // "type": <string> |
| // Tracing technology name, e.g. intel-pt, arm-coresight. |
| // |
| // /* thread trace stopping only */ |
| // "tids": [<decimal integer>] |
| // Individual thread traces to stop. |
| // } |
| // |
| // NOTES |
| // - 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. |
| //---------------------------------------------------------------------- |
| |
| Process trace stopping: |
| send packet: jLLDBTraceStop:{"type":<type>}] |
| read packet: OK/E<error code>;AAAAAAAAA |
| |
| Thread trace stopping: |
| send packet: jLLDBTraceStop:{"type":<type>,"tids":<tids>}] |
| read packet: OK/E<error code>;AAAAAAAAA |
| |
| //---------------------------------------------------------------------- |
| // jLLDBTraceGetState |
| // |
| // BRIEF |
| // 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. |
| // |
| // INPUT SCHEMA |
| // { |
| // "type": <string> |
| // Tracing technology name, e.g. intel-pt, arm-coresight. |
| // } |
| // |
| // 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. |
| // }, |
| // }] |
| // } |
| // |
| // NOTES |
| // - "traceThreads" includes all thread traced by both "process tracing" and |
| // "thread tracing". |
| // |
| // INTEL PT |
| // |
| // Binary data kinds: |
| // - threadTraceBuffer: trace buffer for a thread. |
| // - cpuInfo: contents of the /proc/cpuinfo file. |
| //---------------------------------------------------------------------- |
| |
| send packet: jLLDBTraceGetState:{"type":<type>}] |
| read packet: {...object}/E<error code>;AAAAAAAAA |
| |
| //---------------------------------------------------------------------- |
| // jLLDBTraceGetBinaryData |
| // |
| // BRIEF |
| // 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. |
| // |
| // SCHEMA |
| // The schema for the input is |
| // |
| // { |
| // "type": <string>, |
| // Tracing technology name, e.g. intel-pt, arm-coresight. |
| // "kind": <string>, |
| // Identifier for the data. |
| // "tid"?: <Optional decimal>, |
| // Tid in decimal if the data belongs to a thread. |
| // "offset": <decimal>, |
| // Offset of the data in bytes. |
| // "size": <decimal>, |
| // Number of bytes in to read starting from the offset. |
| // } |
| // |
| // INTEL PT |
| // |
| // Binary data kinds: |
| // - threadTraceBuffer: trace buffer for a thread. |
| // - cpuInfo: contents of the /proc/cpuinfo file. |
| //---------------------------------------------------------------------- |
| |
| send packet: jLLDBTraceGetBinaryData:{"type":<type>,"kind":<query>,"tid":<tid>,"offset":<offset>,"size":<size>}] |
| read packet: <binary data>/E<error code>;AAAAAAAAA |
| |
| //---------------------------------------------------------------------- |
| // "qRegisterInfo<hex-reg-id>" |
| // |
| // BRIEF |
| // Discover register information from the remote GDB server. |
| // |
| // 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. |
| // |
| // NB: As of summer 2015, lldb can get register information from the |
| // "qXfer:features:read:target.xml" FSF gdb standard register packet |
| // where the stub provides register definitions in an XML file. |
| // If qXfer:features:read:target.xml is supported, qRegisterInfo does |
| // not need to be implemented. |
| //---------------------------------------------------------------------- |
| |
| With LLDB, for register information, remote GDB servers can add |
| support for the "qRegisterInfoN" packet where "N" is a zero based |
| base16 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: |
| |
| Key Value |
| ========== ================================================================ |
| 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) |
| fp (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. |
| |
| //---------------------------------------------------------------------- |
| // "qPlatform_shell" |
| // |
| // BRIEF |
| // Run a command in a shell on the connected remote machine. |
| // |
| // PRIORITY TO IMPLEMENT |
| // High. This command allows LLDB clients to run arbitrary shell |
| // commands on a remote host. |
| // |
| /---------------------------------------------------------------------- |
| |
| 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 |
| |
| //---------------------------------------------------------------------- |
| // "qPlatform_mkdir" |
| // |
| // BRIEF |
| // Creates a new directory on the connected remote machine. |
| // |
| // PRIORITY TO IMPLEMENT |
| // Low. This command allows LLDB clients to create new directories on |
| // a remote host. |
| // |
| /---------------------------------------------------------------------- |
| |
| Request: |
| qPlatform_mkdir:<hex-file-mode>,<ascii-hex-path> |
| |
| Reply: |
| F<mkdir-return-code> |
| mkdir called successfully and returned with the given return code |
| Exx |
| An error occurred |
| |
| //---------------------------------------------------------------------- |
| // "qPlatform_chmod" |
| // |
| // BRIEF |
| // Change the permissions of a file on the connected remote machine. |
| // |
| // PRIORITY TO IMPLEMENT |
| // Low. This command allows LLDB clients to change the permissions of |
| // a file on the remote host. |
| // |
| /---------------------------------------------------------------------- |
| |
| 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 |
| |
| //---------------------------------------------------------------------- |
| // "qHostInfo" |
| // |
| // BRIEF |
| // Get information about the host we are remotely connected to. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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. |
| |
| //---------------------------------------------------------------------- |
| // "qGDBServerVersion" |
| // |
| // BRIEF |
| // Get version information about this implementation of the gdb-remote |
| // protocol. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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 |
| |
| //---------------------------------------------------------------------- |
| // "qProcessInfo" |
| // |
| // BRIEF |
| // 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. |
| // e.g. 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 |
| |
| |
| //---------------------------------------------------------------------- |
| // "qShlibInfoAddr" |
| // |
| // BRIEF |
| // Get an address where the dynamic linker stores information about |
| // where shared libraries are loaded. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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 |
| |
| |
| |
| //---------------------------------------------------------------------- |
| // "qThreadStopInfo<tid>" |
| // |
| // BRIEF |
| // Get information about why a thread, whose ID is "<tid>", is stopped. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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. |
| |
| //---------------------------------------------------------------------- |
| // "QThreadSuffixSupported" |
| // |
| // BRIEF |
| // Try to enable thread suffix support for the 'g', 'G', 'p', and 'P' |
| // packets. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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. |
| |
| //---------------------------------------------------------------------- |
| // "_M<size>,<permissions>" |
| // |
| // BRIEF |
| // Allocate memory on the remote target with the specified size and |
| // permissions. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| The allocate memory packet starts with "_M<size>,<permissions>". It returns a |
| raw big endian address value, or "" 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. |
| |
| //---------------------------------------------------------------------- |
| // "_m<addr>" |
| // |
| // BRIEF |
| // Deallocate memory that was previously allocated using an allocate |
| // memory pack. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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 "" if |
| not supported. |
| |
| //---------------------------------------------------------------------- |
| // "qMemoryRegionInfo:<addr>" |
| // |
| // BRIEF |
| // Get information about the address range that contains "<addr>" |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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 base16. 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. |
| |
| 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. |
| |
| //---------------------------------------------------------------------- |
| // "x" - Binary memory read |
| // |
| // 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 |
| // |
| // and you will get an "OK" response. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // 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 |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // QSaveRegisterState |
| // QSaveRegisterState;thread:XXXX; |
| // |
| // BRIEF |
| // 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. |
| // |
| // RESPONSE |
| // unsigned - 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 via a g packet. It should only be implemented if support |
| // for the QRestoreRegisterState is added. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // QRestoreRegisterState:<save_id> |
| // QRestoreRegisterState:<save_id>;thread:XXXX; |
| // |
| // BRIEF |
| // 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. |
| // |
| // RESPONSE |
| // "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 via a g packet. It should only be implemented if support |
| // for the QSaveRegisterState is added. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // qFileLoadAddress:<file_path> |
| // |
| // BRIEF |
| // 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. |
| // |
| // RESPONSE |
| // <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. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // qModuleInfo:<module_path>;<arch triple> |
| // |
| // BRIEF |
| // Get information for a module by given module path and architecture. |
| // |
| // RESPONSE |
| // "(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. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // jModulesInfo:[{"file":"...",triple:"..."}, ...] |
| // |
| // BRIEF |
| // Get information for a list of modules by given module path and |
| // architecture. |
| // |
| // RESPONSE |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // Stop reply packet extensions |
| // |
| // BRIEF |
| // 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. |
| // |
| // DESCRIPTION |
| // 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. |
| // - 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 ignore and "qXfer:libraries:read" |
| // packets should be used to detect any newly loaded shared libraries |
| // |
| // "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: |
| // |
| // KEY VALUE DESCRIPTION |
| // =========== ======== ================================================ |
| // "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". Should be used in conjunction with |
| // the "watch"/"rwatch"/"awatch" key value pairs. |
| // "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" ascii-hex 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. |
| // |
| // "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; |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| |
| //---------------------------------------------------------------------- |
| // PLATFORM EXTENSION - for use as a GDB remote platform |
| //---------------------------------------------------------------------- |
| // "qfProcessInfo" |
| // "qsProcessInfo" |
| // |
| // BRIEF |
| // 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. |
| // |
| // PRIORITY TO IMPLEMENT |
| // Required. The qfProcessInfo packet can be followed by a ':' and |
| // some key value pairs. The key value pairs in the command are: |
| // |
| // KEY VALUE DESCRIPTION |
| // =========== ======== ================================================ |
| // "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" or "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 |
| //---------------------------------------------------------------------- |
| |
| |
| //---------------------------------------------------------------------- |
| // PLATFORM EXTENSION - for use as a GDB remote platform |
| //---------------------------------------------------------------------- |
| // "qLaunchGDBServer" |
| // |
| // BRIEF |
| // Have the remote platform launch a GDB server. |
| // |
| // PRIORITY TO IMPLEMENT |
| // Required. The qLaunchGDBServer packet must be followed by a ':' and |
| // some key value pairs. The key value pairs in the command are: |
| // |
| // KEY VALUE DESCRIPTION |
| // =========== ======== ================================================ |
| // "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. |
| // |
| // 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. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| |
| //---------------------------------------------------------------------- |
| // PLATFORM EXTENSION - for use as a GDB remote platform |
| //---------------------------------------------------------------------- |
| // "qProcessInfoPID:PID" |
| // |
| // BRIEF |
| // Have the remote platform get detailed information on a process by |
| // ID. PID is specified as a decimal integer. |
| // |
| // PRIORITY TO IMPLEMENT |
| // Optional. |
| // |
| // 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: |
| // |
| // KEY VALUE DESCRIPTION |
| // =========== ======== ================================================ |
| // "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 |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // "vAttachName" |
| // |
| // BRIEF |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // "vAttachWait" |
| // |
| // BRIEF |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // "qAttachOrWaitSupported" |
| // |
| // BRIEF |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // "vAttachOrWait" |
| // |
| // BRIEF |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // "jThreadExtendedInfo" |
| // |
| // BRIEF |
| // 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. |
| // |
| // 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. |
| // |
| // This packet takes its arguments in JSON form ( 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 base10. |
| // 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}] |
| // |
| // on the wire. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // "QEnableCompression" |
| // |
| // BRIEF |
| // 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. e.g. |
| // LLDB SENDS: qSupported:xmlRegisters=i386,arm,mips |
| // STUB REPLIES: qXfer:features:read+;SupportedCompressions=lzfse,zlib-deflate,lz4,lzma;DefaultCompressionMinSize=384 |
| // |
| // If lldb knows how to use any of these compression algorithms, it can ask that this |
| // compression mode be enabled. It may optionally change the minimum packet size |
| // where compression is used. Typically small packets do not benefit from compression, |
| // as well as compression headers -- compression is most beneficial with larger packets. |
| // |
| // QEnableCompression:type:zlib-deflate; |
| // or |
| // QEnableCompression:type:zlib-deflate;minsize:512; |
| // |
| // 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 base10>:<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 base10>:<compressed payload>" bytes in the packet. |
| // |
| // The size of the uncompressed payload in base10 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 algorithsm 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 |
| // An Apple proprietary compression algorithm implemented in libcompression. |
| // |
| // lzma |
| // libcompression implements "LZMA level 6", the default compression for the |
| // open source LZMA implementation. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // "jGetLoadedDynamicLibrariesInfos" |
| // |
| // BRIEF |
| // 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 three ways this packet can be used. All three return a dictionary of |
| // binary images formatted the same way. |
| // |
| // On OS X 10.11, iOS 9, tvOS 9, watchOS 2 and earlier, the packet is used like |
| // jGetLoadedDynamicLibrariesInfos:{"image_count":1,"image_list_address":140734800075128} |
| // where the image_list_address is an array of {void* load_addr, void* mod_date, void* pathname} |
| // in the inferior process memory (and image_count is the number of elements in this array). |
| // lldb is using information from the dyld_all_image_infos structure to make these requests to |
| // debugserver. This use is not supported on macOS 10.12, iOS 10, tvOS 10, watchOS 3 or newer. |
| // |
| // On macOS 10.12, iOS 10, tvOS 10, watchOS 3 and newer, there are two calls. One requests information |
| // on all shared libraries: |
| // jGetLoadedDynamicLibrariesInfos:{"fetch_all_solibs":true} |
| // And the second requests information about a list of shared libraries, 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. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // "jThreadsInfo" |
| // |
| // BRIEF |
| // Ask for the server for thread stop information of all threads. |
| // |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| 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. |
| |
| 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! |
| |
| //---------------------------------------------------------------------- |
| // "jGetSharedCacheInfo" |
| // |
| // BRIEF |
| // 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. |
| //---------------------------------------------------------------------- |
| |
| //---------------------------------------------------------------------- |
| // "qQueryGDBServer" |
| // |
| // BRIEF |
| // Ask the platform for the list of gdbservers we have to connect |
| // |
| // PRIORITY TO IMPLEMENT |
| // Low. The packet is required to support connecting to gdbserver started |
| // by the platform instance automatically. |
| //---------------------------------------------------------------------- |
| |
| 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" } |
| ] |