diff options
| -rw-r--r-- | lldb/docs/lldb-gdb-remote.txt | 50 | ||||
| -rw-r--r-- | lldb/tools/debugserver/source/RNBRemote.cpp | 36 |
2 files changed, 86 insertions, 0 deletions
diff --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt index f9537719c90..5c4a10c82b4 100644 --- a/lldb/docs/lldb-gdb-remote.txt +++ b/lldb/docs/lldb-gdb-remote.txt @@ -191,6 +191,24 @@ 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 + +//---------------------------------------------------------------------- // "qRegisterInfo<hex-reg-id>" // // BRIEF @@ -201,6 +219,12 @@ This packet must be sent _prior_ to sending a "A" packet. // 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 @@ -1117,6 +1141,32 @@ for this region. // 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 diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 0c2c742f9f3..dadf479ce81 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -2743,6 +2743,7 @@ RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid) const nub_size_t numthreads = DNBProcessGetNumThreads (pid); if (numthreads > 0) { + std::vector<uint64_t> pc_values; ostrm << std::hex << "threads:"; for (nub_size_t i = 0; i < numthreads; ++i) { @@ -2750,8 +2751,43 @@ RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid) if (i > 0) ostrm << ','; ostrm << std::hex << th; + DNBRegisterValue pc_regval; + if (DNBThreadGetRegisterValueByID (pid, th, REGISTER_SET_GENERIC, GENERIC_REGNUM_PC, &pc_regval)) + { + uint64_t pc = INVALID_NUB_ADDRESS; + if (pc_regval.value.uint64 != INVALID_NUB_ADDRESS) + { + if (pc_regval.info.size == 4) + { + pc = pc_regval.value.uint32; + } + else if (pc_regval.info.size == 8) + { + pc = pc_regval.value.uint64; + } + if (pc != INVALID_NUB_ADDRESS) + { + pc_values.push_back (pc); + } + } + } } ostrm << ';'; + + // If we failed to get any of the thread pc values, the size of our vector will not + // be the same as the # of threads. Don't provide any expedited thread pc values in + // that case. This should not happen. + if (pc_values.size() == numthreads) + { + ostrm << std::hex << "thread-pcs:"; + for (nub_size_t i = 0; i < numthreads; ++i) + { + if (i > 0) + ostrm << ','; + ostrm << std::hex << pc_values[i]; + } + ostrm << ';'; + } } // Include JSON info that describes the stop reason for any threads |

