summaryrefslogtreecommitdiffstats
path: root/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote')
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp376
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h144
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp2469
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h538
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp7508
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h1188
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp154
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h61
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp2074
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h205
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp5426
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h364
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp896
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h128
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp1926
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h181
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp9094
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h711
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp342
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h58
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp569
-rw-r--r--contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h154
22 files changed, 16615 insertions, 17951 deletions
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
new file mode 100644
index 0000000..1e20a09
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -0,0 +1,376 @@
+//===-- GDBRemoteClientBase.cpp ---------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "GDBRemoteClientBase.h"
+
+#include "llvm/ADT/StringExtras.h"
+
+#include "lldb/Target/Process.h"
+#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/LLDBAssert.h"
+
+#include "ProcessGDBRemoteLog.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_gdb_remote;
+using namespace std::chrono;
+
+static const seconds kInterruptTimeout(5);
+
+/////////////////////////
+// GDBRemoteClientBase //
+/////////////////////////
+
+GDBRemoteClientBase::ContinueDelegate::~ContinueDelegate() = default;
+
+GDBRemoteClientBase::GDBRemoteClientBase(const char *comm_name,
+ const char *listener_name)
+ : GDBRemoteCommunication(comm_name, listener_name), m_async_count(0),
+ m_is_running(false), m_should_stop(false) {}
+
+StateType GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(
+ ContinueDelegate &delegate, const UnixSignals &signals,
+ llvm::StringRef payload, StringExtractorGDBRemote &response) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ response.Clear();
+
+ {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ m_continue_packet = payload;
+ m_should_stop = false;
+ }
+ ContinueLock cont_lock(*this);
+ if (!cont_lock)
+ return eStateInvalid;
+ OnRunPacketSent(true);
+
+ for (;;) {
+ PacketResult read_result = ReadPacket(response, kInterruptTimeout, false);
+ switch (read_result) {
+ case PacketResult::ErrorReplyTimeout: {
+ std::lock_guard<std::mutex> lock(m_mutex);
+ if (m_async_count == 0)
+ continue;
+ if (steady_clock::now() >= m_interrupt_time + kInterruptTimeout)
+ return eStateInvalid;
+ }
+ case PacketResult::Success:
+ break;
+ default:
+ if (log)
+ log->Printf("GDBRemoteClientBase::%s () ReadPacket(...) => false",
+ __FUNCTION__);
+ return eStateInvalid;
+ }
+ if (response.Empty())
+ return eStateInvalid;
+
+ const char stop_type = response.GetChar();
+ if (log)
+ log->Printf("GDBRemoteClientBase::%s () got packet: %s", __FUNCTION__,
+ response.GetStringRef().c_str());
+
+ switch (stop_type) {
+ case 'W':
+ case 'X':
+ return eStateExited;
+ case 'E':
+ // ERROR
+ return eStateInvalid;
+ default:
+ if (log)
+ log->Printf("GDBRemoteClientBase::%s () unrecognized async packet",
+ __FUNCTION__);
+ return eStateInvalid;
+ case 'O': {
+ std::string inferior_stdout;
+ response.GetHexByteString(inferior_stdout);
+ delegate.HandleAsyncStdout(inferior_stdout);
+ break;
+ }
+ case 'A':
+ delegate.HandleAsyncMisc(
+ llvm::StringRef(response.GetStringRef()).substr(1));
+ break;
+ case 'J':
+ delegate.HandleAsyncStructuredDataPacket(response.GetStringRef());
+ break;
+ case 'T':
+ case 'S':
+ // Do this with the continue lock held.
+ const bool should_stop = ShouldStop(signals, response);
+ response.SetFilePos(0);
+
+ // The packet we should resume with. In the future
+ // we should check our thread list and "do the right thing"
+ // for new threads that show up while we stop and run async
+ // packets. Setting the packet to 'c' to continue all threads
+ // is the right thing to do 99.99% of the time because if a
+ // thread was single stepping, and we sent an interrupt, we
+ // will notice above that we didn't stop due to an interrupt
+ // but stopped due to stepping and we would _not_ continue.
+ // This packet may get modified by the async actions (e.g. to send a
+ // signal).
+ m_continue_packet = 'c';
+ cont_lock.unlock();
+
+ delegate.HandleStopReply();
+ if (should_stop)
+ return eStateStopped;
+
+ switch (cont_lock.lock()) {
+ case ContinueLock::LockResult::Success:
+ break;
+ case ContinueLock::LockResult::Failed:
+ return eStateInvalid;
+ case ContinueLock::LockResult::Cancelled:
+ return eStateStopped;
+ }
+ OnRunPacketSent(false);
+ break;
+ }
+ }
+}
+
+bool GDBRemoteClientBase::SendAsyncSignal(int signo) {
+ Lock lock(*this, true);
+ if (!lock || !lock.DidInterrupt())
+ return false;
+
+ m_continue_packet = 'C';
+ m_continue_packet += llvm::hexdigit((signo / 16) % 16);
+ m_continue_packet += llvm::hexdigit(signo % 16);
+ return true;
+}
+
+bool GDBRemoteClientBase::Interrupt() {
+ Lock lock(*this, true);
+ if (!lock.DidInterrupt())
+ return false;
+ m_should_stop = true;
+ return true;
+}
+GDBRemoteCommunication::PacketResult
+GDBRemoteClientBase::SendPacketAndWaitForResponse(
+ llvm::StringRef payload, StringExtractorGDBRemote &response,
+ bool send_async) {
+ Lock lock(*this, send_async);
+ if (!lock) {
+ if (Log *log =
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS))
+ log->Printf("GDBRemoteClientBase::%s failed to get mutex, not sending "
+ "packet '%.*s' (send_async=%d)",
+ __FUNCTION__, int(payload.size()), payload.data(),
+ send_async);
+ return PacketResult::ErrorSendFailed;
+ }
+
+ return SendPacketAndWaitForResponseNoLock(payload, response);
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteClientBase::SendPacketAndWaitForResponseNoLock(
+ llvm::StringRef payload, StringExtractorGDBRemote &response) {
+ PacketResult packet_result = SendPacketNoLock(payload);
+ if (packet_result != PacketResult::Success)
+ return packet_result;
+
+ const size_t max_response_retries = 3;
+ for (size_t i = 0; i < max_response_retries; ++i) {
+ packet_result = ReadPacket(response, GetPacketTimeout(), true);
+ // Make sure we received a response
+ if (packet_result != PacketResult::Success)
+ return packet_result;
+ // Make sure our response is valid for the payload that was sent
+ if (response.ValidateResponse())
+ return packet_result;
+ // Response says it wasn't valid
+ Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS);
+ if (log)
+ log->Printf(
+ "error: packet with payload \"%.*s\" got invalid response \"%s\": %s",
+ int(payload.size()), payload.data(), response.GetStringRef().c_str(),
+ (i == (max_response_retries - 1))
+ ? "using invalid response and giving up"
+ : "ignoring response and waiting for another");
+ }
+ return packet_result;
+}
+
+bool GDBRemoteClientBase::SendvContPacket(llvm::StringRef payload,
+ StringExtractorGDBRemote &response) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
+
+ // we want to lock down packet sending while we continue
+ Lock lock(*this, true);
+
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationClient::%s () sending vCont packet: %.*s",
+ __FUNCTION__, int(payload.size()), payload.data());
+
+ if (SendPacketNoLock(payload) != PacketResult::Success)
+ return false;
+
+ OnRunPacketSent(true);
+
+ // wait for the response to the vCont
+ if (ReadPacket(response, llvm::None, false) == PacketResult::Success) {
+ if (response.IsOKResponse())
+ return true;
+ }
+
+ return false;
+}
+bool GDBRemoteClientBase::ShouldStop(const UnixSignals &signals,
+ StringExtractorGDBRemote &response) {
+ std::lock_guard<std::mutex> lock(m_mutex);
+
+ if (m_async_count == 0)
+ return true; // We were not interrupted. The process stopped on its own.
+
+ // Older debugserver stubs (before April 2016) can return two
+ // stop-reply packets in response to a ^C packet.
+ // Additionally, all debugservers still return two stop replies if
+ // the inferior stops due to some other reason before the remote
+ // stub manages to interrupt it. We need to wait for this
+ // additional packet to make sure the packet sequence does not get
+ // skewed.
+ StringExtractorGDBRemote extra_stop_reply_packet;
+ ReadPacket(extra_stop_reply_packet, milliseconds(100), false);
+
+ // Interrupting is typically done using SIGSTOP or SIGINT, so if
+ // the process stops with some other signal, we definitely want to
+ // stop.
+ const uint8_t signo = response.GetHexU8(UINT8_MAX);
+ if (signo != signals.GetSignalNumberFromName("SIGSTOP") &&
+ signo != signals.GetSignalNumberFromName("SIGINT"))
+ return true;
+
+ // We probably only stopped to perform some async processing, so continue
+ // after that is done.
+ // TODO: This is not 100% correct, as the process may have been stopped with
+ // SIGINT or SIGSTOP that was not caused by us (e.g. raise(SIGINT)). This will
+ // normally cause a stop, but if it's done concurrently with a async
+ // interrupt, that stop will get eaten (llvm.org/pr20231).
+ return false;
+}
+
+void GDBRemoteClientBase::OnRunPacketSent(bool first) {
+ if (first)
+ BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
+}
+
+///////////////////////////////////////
+// GDBRemoteClientBase::ContinueLock //
+///////////////////////////////////////
+
+GDBRemoteClientBase::ContinueLock::ContinueLock(GDBRemoteClientBase &comm)
+ : m_comm(comm), m_acquired(false) {
+ lock();
+}
+
+GDBRemoteClientBase::ContinueLock::~ContinueLock() {
+ if (m_acquired)
+ unlock();
+}
+
+void GDBRemoteClientBase::ContinueLock::unlock() {
+ lldbassert(m_acquired);
+ {
+ std::unique_lock<std::mutex> lock(m_comm.m_mutex);
+ m_comm.m_is_running = false;
+ }
+ m_comm.m_cv.notify_all();
+ m_acquired = false;
+}
+
+GDBRemoteClientBase::ContinueLock::LockResult
+GDBRemoteClientBase::ContinueLock::lock() {
+ Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS);
+ if (log)
+ log->Printf("GDBRemoteClientBase::ContinueLock::%s() resuming with %s",
+ __FUNCTION__, m_comm.m_continue_packet.c_str());
+
+ lldbassert(!m_acquired);
+ std::unique_lock<std::mutex> lock(m_comm.m_mutex);
+ m_comm.m_cv.wait(lock, [this] { return m_comm.m_async_count == 0; });
+ if (m_comm.m_should_stop) {
+ m_comm.m_should_stop = false;
+ if (log)
+ log->Printf("GDBRemoteClientBase::ContinueLock::%s() cancelled",
+ __FUNCTION__);
+ return LockResult::Cancelled;
+ }
+ if (m_comm.SendPacketNoLock(m_comm.m_continue_packet) !=
+ PacketResult::Success)
+ return LockResult::Failed;
+
+ lldbassert(!m_comm.m_is_running);
+ m_comm.m_is_running = true;
+ m_acquired = true;
+ return LockResult::Success;
+}
+
+///////////////////////////////
+// GDBRemoteClientBase::Lock //
+///////////////////////////////
+
+GDBRemoteClientBase::Lock::Lock(GDBRemoteClientBase &comm, bool interrupt)
+ : m_async_lock(comm.m_async_mutex, std::defer_lock), m_comm(comm),
+ m_acquired(false), m_did_interrupt(false) {
+ SyncWithContinueThread(interrupt);
+ if (m_acquired)
+ m_async_lock.lock();
+}
+
+void GDBRemoteClientBase::Lock::SyncWithContinueThread(bool interrupt) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ std::unique_lock<std::mutex> lock(m_comm.m_mutex);
+ if (m_comm.m_is_running && !interrupt)
+ return; // We were asked to avoid interrupting the sender. Lock is not
+ // acquired.
+
+ ++m_comm.m_async_count;
+ if (m_comm.m_is_running) {
+ if (m_comm.m_async_count == 1) {
+ // The sender has sent the continue packet and we are the first async
+ // packet. Let's interrupt it.
+ const char ctrl_c = '\x03';
+ ConnectionStatus status = eConnectionStatusSuccess;
+ size_t bytes_written = m_comm.Write(&ctrl_c, 1, status, NULL);
+ if (bytes_written == 0) {
+ --m_comm.m_async_count;
+ if (log)
+ log->Printf("GDBRemoteClientBase::Lock::Lock failed to send "
+ "interrupt packet");
+ return;
+ }
+ if (log)
+ log->PutCString("GDBRemoteClientBase::Lock::Lock sent packet: \\x03");
+ m_comm.m_interrupt_time = steady_clock::now();
+ }
+ m_comm.m_cv.wait(lock, [this] { return m_comm.m_is_running == false; });
+ m_did_interrupt = true;
+ }
+ m_acquired = true;
+}
+
+GDBRemoteClientBase::Lock::~Lock() {
+ if (!m_acquired)
+ return;
+ {
+ std::unique_lock<std::mutex> lock(m_comm.m_mutex);
+ --m_comm.m_async_count;
+ }
+ m_comm.m_cv.notify_one();
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
new file mode 100644
index 0000000..2646405
--- /dev/null
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
@@ -0,0 +1,144 @@
+//===-- GDBRemoteClientBase.h -----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_GDBRemoteClientBase_h_
+#define liblldb_GDBRemoteClientBase_h_
+
+#include "GDBRemoteCommunication.h"
+
+#include <condition_variable>
+
+namespace lldb_private {
+namespace process_gdb_remote {
+
+class GDBRemoteClientBase : public GDBRemoteCommunication {
+public:
+ struct ContinueDelegate {
+ virtual ~ContinueDelegate();
+ virtual void HandleAsyncStdout(llvm::StringRef out) = 0;
+ virtual void HandleAsyncMisc(llvm::StringRef data) = 0;
+ virtual void HandleStopReply() = 0;
+
+ // =========================================================================
+ /// Process asynchronously-received structured data.
+ ///
+ /// @param[in] data
+ /// The complete data packet, expected to start with JSON-async.
+ // =========================================================================
+ virtual void HandleAsyncStructuredDataPacket(llvm::StringRef data) = 0;
+ };
+
+ GDBRemoteClientBase(const char *comm_name, const char *listener_name);
+
+ bool SendAsyncSignal(int signo);
+
+ bool Interrupt();
+
+ lldb::StateType SendContinuePacketAndWaitForResponse(
+ ContinueDelegate &delegate, const UnixSignals &signals,
+ llvm::StringRef payload, StringExtractorGDBRemote &response);
+
+ PacketResult SendPacketAndWaitForResponse(llvm::StringRef payload,
+ StringExtractorGDBRemote &response,
+ bool send_async);
+
+ bool SendvContPacket(llvm::StringRef payload,
+ StringExtractorGDBRemote &response);
+
+ class Lock {
+ public:
+ Lock(GDBRemoteClientBase &comm, bool interrupt);
+ ~Lock();
+
+ explicit operator bool() { return m_acquired; }
+
+ // Whether we had to interrupt the continue thread to acquire the
+ // connection.
+ bool DidInterrupt() const { return m_did_interrupt; }
+
+ private:
+ std::unique_lock<std::recursive_mutex> m_async_lock;
+ GDBRemoteClientBase &m_comm;
+ bool m_acquired;
+ bool m_did_interrupt;
+
+ void SyncWithContinueThread(bool interrupt);
+ };
+
+protected:
+ PacketResult
+ SendPacketAndWaitForResponseNoLock(llvm::StringRef payload,
+ StringExtractorGDBRemote &response);
+
+ virtual void OnRunPacketSent(bool first);
+
+private:
+ // Variables handling synchronization between the Continue thread and any
+ // other threads
+ // wishing to send packets over the connection. Either the continue thread has
+ // control over
+ // the connection (m_is_running == true) or the connection is free for an
+ // arbitrary number of
+ // other senders to take which indicate their interest by incrementing
+ // m_async_count.
+ // Semantics of individual states:
+ // - m_continue_packet == false, m_async_count == 0: connection is free
+ // - m_continue_packet == true, m_async_count == 0: only continue thread is
+ // present
+ // - m_continue_packet == true, m_async_count > 0: continue thread has
+ // control, async threads
+ // should interrupt it and wait for it to set m_continue_packet to false
+ // - m_continue_packet == false, m_async_count > 0: async threads have
+ // control, continue
+ // thread needs to wait for them to finish (m_async_count goes down to 0).
+ std::mutex m_mutex;
+ std::condition_variable m_cv;
+ // Packet with which to resume after an async interrupt. Can be changed by an
+ // async thread
+ // e.g. to inject a signal.
+ std::string m_continue_packet;
+ // When was the interrupt packet sent. Used to make sure we time out if the
+ // stub does not
+ // respond to interrupt requests.
+ std::chrono::time_point<std::chrono::steady_clock> m_interrupt_time;
+ uint32_t m_async_count;
+ bool m_is_running;
+ bool m_should_stop; // Whether we should resume after a stop.
+ // end of continue thread synchronization block
+
+ // This handles the synchronization between individual async threads. For now
+ // they just use a
+ // simple mutex.
+ std::recursive_mutex m_async_mutex;
+
+ bool ShouldStop(const UnixSignals &signals,
+ StringExtractorGDBRemote &response);
+
+ class ContinueLock {
+ public:
+ enum class LockResult { Success, Cancelled, Failed };
+
+ explicit ContinueLock(GDBRemoteClientBase &comm);
+ ~ContinueLock();
+ explicit operator bool() { return m_acquired; }
+
+ LockResult lock();
+
+ void unlock();
+
+ private:
+ GDBRemoteClientBase &m_comm;
+ bool m_acquired;
+ };
+};
+
+} // namespace process_gdb_remote
+} // namespace lldb_private
+
+#endif // liblldb_GDBRemoteCommunicationClient_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index f164b14..bd87521 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
#include "GDBRemoteCommunication.h"
// C Includes
@@ -29,25 +28,25 @@
#include "lldb/Host/Socket.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/ThreadLauncher.h"
-#include "lldb/Host/TimeValue.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/ScopedPrinter.h"
// Project includes
#include "ProcessGDBRemoteLog.h"
#if defined(__APPLE__)
-# define DEBUGSERVER_BASENAME "debugserver"
+#define DEBUGSERVER_BASENAME "debugserver"
#else
-# define DEBUGSERVER_BASENAME "lldb-server"
+#define DEBUGSERVER_BASENAME "lldb-server"
#endif
-#if defined (HAVE_LIBCOMPRESSION)
+#if defined(HAVE_LIBCOMPRESSION)
#include <compression.h>
#endif
-#if defined (HAVE_LIBZ)
+#if defined(HAVE_LIBZ)
#include <zlib.h>
#endif
@@ -55,1449 +54,1309 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
-GDBRemoteCommunication::History::History (uint32_t size) :
- m_packets(),
- m_curr_idx (0),
- m_total_packet_count (0),
- m_dumped_to_log (false)
-{
- m_packets.resize(size);
+GDBRemoteCommunication::History::History(uint32_t size)
+ : m_packets(), m_curr_idx(0), m_total_packet_count(0),
+ m_dumped_to_log(false) {
+ m_packets.resize(size);
}
-GDBRemoteCommunication::History::~History ()
-{
+GDBRemoteCommunication::History::~History() {}
+
+void GDBRemoteCommunication::History::AddPacket(char packet_char,
+ PacketType type,
+ uint32_t bytes_transmitted) {
+ const size_t size = m_packets.size();
+ if (size > 0) {
+ const uint32_t idx = GetNextIndex();
+ m_packets[idx].packet.assign(1, packet_char);
+ m_packets[idx].type = type;
+ m_packets[idx].bytes_transmitted = bytes_transmitted;
+ m_packets[idx].packet_idx = m_total_packet_count;
+ m_packets[idx].tid = Host::GetCurrentThreadID();
+ }
}
-void
-GDBRemoteCommunication::History::AddPacket (char packet_char,
- PacketType type,
- uint32_t bytes_transmitted)
-{
- const size_t size = m_packets.size();
- if (size > 0)
- {
- const uint32_t idx = GetNextIndex();
- m_packets[idx].packet.assign (1, packet_char);
- m_packets[idx].type = type;
- m_packets[idx].bytes_transmitted = bytes_transmitted;
- m_packets[idx].packet_idx = m_total_packet_count;
- m_packets[idx].tid = Host::GetCurrentThreadID();
- }
+void GDBRemoteCommunication::History::AddPacket(const std::string &src,
+ uint32_t src_len,
+ PacketType type,
+ uint32_t bytes_transmitted) {
+ const size_t size = m_packets.size();
+ if (size > 0) {
+ const uint32_t idx = GetNextIndex();
+ m_packets[idx].packet.assign(src, 0, src_len);
+ m_packets[idx].type = type;
+ m_packets[idx].bytes_transmitted = bytes_transmitted;
+ m_packets[idx].packet_idx = m_total_packet_count;
+ m_packets[idx].tid = Host::GetCurrentThreadID();
+ }
}
-void
-GDBRemoteCommunication::History::AddPacket (const std::string &src,
- uint32_t src_len,
- PacketType type,
- uint32_t bytes_transmitted)
-{
- const size_t size = m_packets.size();
- if (size > 0)
- {
- const uint32_t idx = GetNextIndex();
- m_packets[idx].packet.assign (src, 0, src_len);
- m_packets[idx].type = type;
- m_packets[idx].bytes_transmitted = bytes_transmitted;
- m_packets[idx].packet_idx = m_total_packet_count;
- m_packets[idx].tid = Host::GetCurrentThreadID();
- }
+void GDBRemoteCommunication::History::Dump(Stream &strm) const {
+ const uint32_t size = GetNumPacketsInHistory();
+ const uint32_t first_idx = GetFirstSavedPacketIndex();
+ const uint32_t stop_idx = m_curr_idx + size;
+ for (uint32_t i = first_idx; i < stop_idx; ++i) {
+ const uint32_t idx = NormalizeIndex(i);
+ const Entry &entry = m_packets[idx];
+ if (entry.type == ePacketTypeInvalid || entry.packet.empty())
+ break;
+ strm.Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n",
+ entry.packet_idx, entry.tid, entry.bytes_transmitted,
+ (entry.type == ePacketTypeSend) ? "send" : "read",
+ entry.packet.c_str());
+ }
}
-void
-GDBRemoteCommunication::History::Dump (Stream &strm) const
-{
- const uint32_t size = GetNumPacketsInHistory ();
- const uint32_t first_idx = GetFirstSavedPacketIndex ();
+void GDBRemoteCommunication::History::Dump(Log *log) const {
+ if (log && !m_dumped_to_log) {
+ m_dumped_to_log = true;
+ const uint32_t size = GetNumPacketsInHistory();
+ const uint32_t first_idx = GetFirstSavedPacketIndex();
const uint32_t stop_idx = m_curr_idx + size;
- for (uint32_t i = first_idx; i < stop_idx; ++i)
- {
- const uint32_t idx = NormalizeIndex (i);
- const Entry &entry = m_packets[idx];
- if (entry.type == ePacketTypeInvalid || entry.packet.empty())
- break;
- strm.Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s\n",
- entry.packet_idx,
- entry.tid,
- entry.bytes_transmitted,
- (entry.type == ePacketTypeSend) ? "send" : "read",
- entry.packet.c_str());
- }
-}
-
-void
-GDBRemoteCommunication::History::Dump (Log *log) const
-{
- if (log && !m_dumped_to_log)
- {
- m_dumped_to_log = true;
- const uint32_t size = GetNumPacketsInHistory ();
- const uint32_t first_idx = GetFirstSavedPacketIndex ();
- const uint32_t stop_idx = m_curr_idx + size;
- for (uint32_t i = first_idx; i < stop_idx; ++i)
- {
- const uint32_t idx = NormalizeIndex (i);
- const Entry &entry = m_packets[idx];
- if (entry.type == ePacketTypeInvalid || entry.packet.empty())
- break;
- log->Printf ("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s",
- entry.packet_idx,
- entry.tid,
- entry.bytes_transmitted,
- (entry.type == ePacketTypeSend) ? "send" : "read",
- entry.packet.c_str());
- }
+ for (uint32_t i = first_idx; i < stop_idx; ++i) {
+ const uint32_t idx = NormalizeIndex(i);
+ const Entry &entry = m_packets[idx];
+ if (entry.type == ePacketTypeInvalid || entry.packet.empty())
+ break;
+ log->Printf("history[%u] tid=0x%4.4" PRIx64 " <%4u> %s packet: %s",
+ entry.packet_idx, entry.tid, entry.bytes_transmitted,
+ (entry.type == ePacketTypeSend) ? "send" : "read",
+ entry.packet.c_str());
}
+ }
}
//----------------------------------------------------------------------
// GDBRemoteCommunication constructor
//----------------------------------------------------------------------
-GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
- const char *listener_name) :
- Communication(comm_name),
+GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name,
+ const char *listener_name)
+ : Communication(comm_name),
#ifdef LLDB_CONFIGURATION_DEBUG
- m_packet_timeout (1000),
+ m_packet_timeout(1000),
#else
- m_packet_timeout (1),
+ m_packet_timeout(1),
#endif
- m_echo_number(0),
- m_supports_qEcho (eLazyBoolCalculate),
- m_sequence_mutex (Mutex::eMutexTypeRecursive),
- m_public_is_running (false),
- m_private_is_running (false),
- m_history (512),
- m_send_acks (true),
- m_compression_type (CompressionType::None),
- m_listen_url ()
-{
+ m_echo_number(0), m_supports_qEcho(eLazyBoolCalculate), m_history(512),
+ m_send_acks(true), m_compression_type(CompressionType::None),
+ m_listen_url() {
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-GDBRemoteCommunication::~GDBRemoteCommunication()
-{
- if (IsConnected())
- {
- Disconnect();
- }
-
- // Stop the communications read thread which is used to parse all
- // incoming packets. This function will block until the read
- // thread returns.
- if (m_read_thread_enabled)
- StopReadThread();
+GDBRemoteCommunication::~GDBRemoteCommunication() {
+ if (IsConnected()) {
+ Disconnect();
+ }
+
+ // Stop the communications read thread which is used to parse all
+ // incoming packets. This function will block until the read
+ // thread returns.
+ if (m_read_thread_enabled)
+ StopReadThread();
}
-char
-GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length)
-{
- int checksum = 0;
+char GDBRemoteCommunication::CalculcateChecksum(llvm::StringRef payload) {
+ int checksum = 0;
- for (size_t i = 0; i < payload_length; ++i)
- checksum += payload[i];
+ for (char c : payload)
+ checksum += c;
- return checksum & 255;
+ return checksum & 255;
}
-size_t
-GDBRemoteCommunication::SendAck ()
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
- ConnectionStatus status = eConnectionStatusSuccess;
- char ch = '+';
- const size_t bytes_written = Write (&ch, 1, status, NULL);
- if (log)
- log->Printf ("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
- m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
- return bytes_written;
+size_t GDBRemoteCommunication::SendAck() {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
+ ConnectionStatus status = eConnectionStatusSuccess;
+ char ch = '+';
+ const size_t bytes_written = Write(&ch, 1, status, NULL);
+ if (log)
+ log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
+ m_history.AddPacket(ch, History::ePacketTypeSend, bytes_written);
+ return bytes_written;
}
-size_t
-GDBRemoteCommunication::SendNack ()
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
- ConnectionStatus status = eConnectionStatusSuccess;
- char ch = '-';
- const size_t bytes_written = Write (&ch, 1, status, NULL);
- if (log)
- log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
- m_history.AddPacket (ch, History::ePacketTypeSend, bytes_written);
- return bytes_written;
+size_t GDBRemoteCommunication::SendNack() {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
+ ConnectionStatus status = eConnectionStatusSuccess;
+ char ch = '-';
+ const size_t bytes_written = Write(&ch, 1, status, NULL);
+ if (log)
+ log->Printf("<%4" PRIu64 "> send packet: %c", (uint64_t)bytes_written, ch);
+ m_history.AddPacket(ch, History::ePacketTypeSend, bytes_written);
+ return bytes_written;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunication::SendPacket (const char *payload, size_t payload_length)
-{
- Mutex::Locker locker(m_sequence_mutex);
- return SendPacketNoLock (payload, payload_length);
-}
+GDBRemoteCommunication::SendPacketNoLock(llvm::StringRef payload) {
+ if (IsConnected()) {
+ StreamString packet(0, 4, eByteOrderBig);
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_length)
-{
- if (IsConnected())
- {
- StreamString packet(0, 4, eByteOrderBig);
-
- packet.PutChar('$');
- packet.Write (payload, payload_length);
- packet.PutChar('#');
- packet.PutHex8(CalculcateChecksum (payload, payload_length));
-
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
- ConnectionStatus status = eConnectionStatusSuccess;
- const char *packet_data = packet.GetData();
- const size_t packet_length = packet.GetSize();
- size_t bytes_written = Write (packet_data, packet_length, status, NULL);
- if (log)
- {
- size_t binary_start_offset = 0;
- if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) == 0)
- {
- const char *first_comma = strchr(packet_data, ',');
- if (first_comma)
- {
- const char *second_comma = strchr(first_comma + 1, ',');
- if (second_comma)
- binary_start_offset = second_comma - packet_data + 1;
- }
- }
-
- // If logging was just enabled and we have history, then dump out what
- // we have to the log so we get the historical context. The Dump() call that
- // logs all of the packet will set a boolean so that we don't dump this more
- // than once
- if (!m_history.DidDumpToLog ())
- m_history.Dump (log);
-
- if (binary_start_offset)
- {
- StreamString strm;
- // Print non binary data header
- strm.Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)binary_start_offset, packet_data);
- const uint8_t *p;
- // Print binary data exactly as sent
- for (p = (const uint8_t*)packet_data + binary_start_offset; *p != '#'; ++p)
- strm.Printf("\\x%2.2x", *p);
- // Print the checksum
- strm.Printf("%*s", (int)3, p);
- log->PutCString(strm.GetString().c_str());
- }
- else
- log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written, (int)packet_length, packet_data);
- }
+ packet.PutChar('$');
+ packet.Write(payload.data(), payload.size());
+ packet.PutChar('#');
+ packet.PutHex8(CalculcateChecksum(payload));
- m_history.AddPacket (packet.GetString(), packet_length, History::ePacketTypeSend, bytes_written);
-
-
- if (bytes_written == packet_length)
- {
- if (GetSendAcks ())
- return GetAck ();
- else
- return PacketResult::Success;
- }
- else
- {
- if (log)
- log->Printf ("error: failed to send packet: %.*s", (int)packet_length, packet_data);
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
+ ConnectionStatus status = eConnectionStatusSuccess;
+ // TODO: Don't shimmy through a std::string, just use StringRef.
+ std::string packet_str = packet.GetString();
+ const char *packet_data = packet_str.c_str();
+ const size_t packet_length = packet.GetSize();
+ size_t bytes_written = Write(packet_data, packet_length, status, NULL);
+ if (log) {
+ size_t binary_start_offset = 0;
+ if (strncmp(packet_data, "$vFile:pwrite:", strlen("$vFile:pwrite:")) ==
+ 0) {
+ const char *first_comma = strchr(packet_data, ',');
+ if (first_comma) {
+ const char *second_comma = strchr(first_comma + 1, ',');
+ if (second_comma)
+ binary_start_offset = second_comma - packet_data + 1;
}
+ }
+
+ // If logging was just enabled and we have history, then dump out what
+ // we have to the log so we get the historical context. The Dump() call
+ // that
+ // logs all of the packet will set a boolean so that we don't dump this
+ // more
+ // than once
+ if (!m_history.DidDumpToLog())
+ m_history.Dump(log);
+
+ if (binary_start_offset) {
+ StreamString strm;
+ // Print non binary data header
+ strm.Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written,
+ (int)binary_start_offset, packet_data);
+ const uint8_t *p;
+ // Print binary data exactly as sent
+ for (p = (const uint8_t *)packet_data + binary_start_offset; *p != '#';
+ ++p)
+ strm.Printf("\\x%2.2x", *p);
+ // Print the checksum
+ strm.Printf("%*s", (int)3, p);
+ log->PutString(strm.GetString());
+ } else
+ log->Printf("<%4" PRIu64 "> send packet: %.*s", (uint64_t)bytes_written,
+ (int)packet_length, packet_data);
}
- return PacketResult::ErrorSendFailed;
-}
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunication::GetAck ()
-{
- StringExtractorGDBRemote packet;
- PacketResult result = ReadPacket (packet, GetPacketTimeoutInMicroSeconds (), false);
- if (result == PacketResult::Success)
- {
- if (packet.GetResponseType() == StringExtractorGDBRemote::ResponseType::eAck)
- return PacketResult::Success;
- else
- return PacketResult::ErrorSendAck;
- }
- return result;
-}
+ m_history.AddPacket(packet.GetString(), packet_length,
+ History::ePacketTypeSend, bytes_written);
-bool
-GDBRemoteCommunication::GetSequenceMutex (Mutex::Locker& locker, const char *failure_message)
-{
- if (IsRunning())
- return locker.TryLock (m_sequence_mutex, failure_message);
-
- locker.Lock (m_sequence_mutex);
- return true;
+ if (bytes_written == packet_length) {
+ if (GetSendAcks())
+ return GetAck();
+ else
+ return PacketResult::Success;
+ } else {
+ if (log)
+ log->Printf("error: failed to send packet: %.*s", (int)packet_length,
+ packet_data);
+ }
+ }
+ return PacketResult::ErrorSendFailed;
}
-
-bool
-GDBRemoteCommunication::WaitForNotRunningPrivate (const TimeValue *timeout_ptr)
-{
- return m_private_is_running.WaitForValueEqualTo (false, timeout_ptr, NULL);
+GDBRemoteCommunication::PacketResult GDBRemoteCommunication::GetAck() {
+ StringExtractorGDBRemote packet;
+ PacketResult result = ReadPacket(packet, GetPacketTimeout(), false);
+ if (result == PacketResult::Success) {
+ if (packet.GetResponseType() ==
+ StringExtractorGDBRemote::ResponseType::eAck)
+ return PacketResult::Success;
+ else
+ return PacketResult::ErrorSendAck;
+ }
+ return result;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunication::ReadPacket (StringExtractorGDBRemote &response, uint32_t timeout_usec, bool sync_on_timeout)
-{
- if (m_read_thread_enabled)
- return PopPacketFromQueue (response, timeout_usec);
- else
- return WaitForPacketWithTimeoutMicroSecondsNoLock (response, timeout_usec, sync_on_timeout);
+GDBRemoteCommunication::ReadPacket(StringExtractorGDBRemote &response,
+ Timeout<std::micro> timeout,
+ bool sync_on_timeout) {
+ if (m_read_thread_enabled)
+ return PopPacketFromQueue(response, timeout);
+ else
+ return WaitForPacketNoLock(response, timeout, sync_on_timeout);
}
-
// This function is called when a packet is requested.
// A whole packet is popped from the packet queue and returned to the caller.
// Packets are placed into this queue from the communication read thread.
// See GDBRemoteCommunication::AppendBytesToCache.
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunication::PopPacketFromQueue (StringExtractorGDBRemote &response, uint32_t timeout_usec)
-{
- // Calculate absolute timeout value
- TimeValue timeout = TimeValue::Now();
- timeout.OffsetWithMicroSeconds(timeout_usec);
-
- do
- {
- // scope for the mutex
- {
- // lock down the packet queue
- Mutex::Locker locker(m_packet_queue_mutex);
-
- // Wait on condition variable.
- if (m_packet_queue.size() == 0)
- m_condition_queue_not_empty.Wait(m_packet_queue_mutex, &timeout);
-
- if (m_packet_queue.size() > 0)
- {
- // get the front element of the queue
- response = m_packet_queue.front();
-
- // remove the front element
- m_packet_queue.pop();
-
- // we got a packet
- return PacketResult::Success;
- }
- }
-
- // Disconnected
- if (!IsConnected())
- return PacketResult::ErrorDisconnected;
-
- // Loop while not timed out
- } while (TimeValue::Now() < timeout);
-
- return PacketResult::ErrorReplyTimeout;
+GDBRemoteCommunication::PopPacketFromQueue(StringExtractorGDBRemote &response,
+ Timeout<std::micro> timeout) {
+ auto pred = [&] { return !m_packet_queue.empty() && IsConnected(); };
+ // lock down the packet queue
+ std::unique_lock<std::mutex> lock(m_packet_queue_mutex);
+
+ if (!timeout)
+ m_condition_queue_not_empty.wait(lock, pred);
+ else {
+ if (!m_condition_queue_not_empty.wait_for(lock, *timeout, pred))
+ return PacketResult::ErrorReplyTimeout;
+ if (!IsConnected())
+ return PacketResult::ErrorDisconnected;
+ }
+
+ // get the front element of the queue
+ response = m_packet_queue.front();
+
+ // remove the front element
+ m_packet_queue.pop();
+
+ // we got a packet
+ return PacketResult::Success;
}
-
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunication::WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &packet, uint32_t timeout_usec, bool sync_on_timeout)
-{
- uint8_t buffer[8192];
- Error error;
+GDBRemoteCommunication::WaitForPacketNoLock(StringExtractorGDBRemote &packet,
+ Timeout<std::micro> timeout,
+ bool sync_on_timeout) {
+ uint8_t buffer[8192];
+ Error error;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS | GDBR_LOG_VERBOSE));
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS |
+ GDBR_LOG_VERBOSE));
- // Check for a packet from our cache first without trying any reading...
- if (CheckForPacket(NULL, 0, packet) != PacketType::Invalid)
- return PacketResult::Success;
+ // Check for a packet from our cache first without trying any reading...
+ if (CheckForPacket(NULL, 0, packet) != PacketType::Invalid)
+ return PacketResult::Success;
- bool timed_out = false;
- bool disconnected = false;
- while (IsConnected() && !timed_out)
- {
- lldb::ConnectionStatus status = eConnectionStatusNoConnection;
- size_t bytes_read = Read (buffer, sizeof(buffer), timeout_usec, status, &error);
-
- if (log)
- log->Printf ("%s: Read (buffer, (sizeof(buffer), timeout_usec = 0x%x, status = %s, error = %s) => bytes_read = %" PRIu64,
- __PRETTY_FUNCTION__,
- timeout_usec,
- Communication::ConnectionStatusAsCString (status),
- error.AsCString(),
- (uint64_t)bytes_read);
-
- if (bytes_read > 0)
- {
- if (CheckForPacket(buffer, bytes_read, packet) != PacketType::Invalid)
- return PacketResult::Success;
- }
- else
- {
- switch (status)
- {
- case eConnectionStatusTimedOut:
- case eConnectionStatusInterrupted:
- if (sync_on_timeout)
- {
- //------------------------------------------------------------------
- /// Sync the remote GDB server and make sure we get a response that
- /// corresponds to what we send.
- ///
- /// Sends a "qEcho" packet and makes sure it gets the exact packet
- /// echoed back. If the qEcho packet isn't supported, we send a qC
- /// packet and make sure we get a valid thread ID back. We use the
- /// "qC" packet since its response if very unique: is responds with
- /// "QC%x" where %x is the thread ID of the current thread. This
- /// makes the response unique enough from other packet responses to
- /// ensure we are back on track.
- ///
- /// This packet is needed after we time out sending a packet so we
- /// can ensure that we are getting the response for the packet we
- /// are sending. There are no sequence IDs in the GDB remote
- /// protocol (there used to be, but they are not supported anymore)
- /// so if you timeout sending packet "abc", you might then send
- /// packet "cde" and get the response for the previous "abc" packet.
- /// Many responses are "OK" or "" (unsupported) or "EXX" (error) so
- /// many responses for packets can look like responses for other
- /// packets. So if we timeout, we need to ensure that we can get
- /// back on track. If we can't get back on track, we must
- /// disconnect.
- //------------------------------------------------------------------
- bool sync_success = false;
- bool got_actual_response = false;
- // We timed out, we need to sync back up with the
- char echo_packet[32];
- int echo_packet_len = 0;
- RegularExpression response_regex;
-
- if (m_supports_qEcho == eLazyBoolYes)
- {
- echo_packet_len = ::snprintf (echo_packet, sizeof(echo_packet), "qEcho:%u", ++m_echo_number);
- std::string regex_str = "^";
- regex_str += echo_packet;
- regex_str += "$";
- response_regex.Compile(regex_str.c_str());
- }
- else
- {
- echo_packet_len = ::snprintf (echo_packet, sizeof(echo_packet), "qC");
- response_regex.Compile("^QC[0-9A-Fa-f]+$");
- }
-
- PacketResult echo_packet_result = SendPacketNoLock (echo_packet, echo_packet_len);
- if (echo_packet_result == PacketResult::Success)
- {
- const uint32_t max_retries = 3;
- uint32_t successful_responses = 0;
- for (uint32_t i=0; i<max_retries; ++i)
- {
- StringExtractorGDBRemote echo_response;
- echo_packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (echo_response, timeout_usec, false);
- if (echo_packet_result == PacketResult::Success)
- {
- ++successful_responses;
- if (response_regex.Execute(echo_response.GetStringRef().c_str()))
- {
- sync_success = true;
- break;
- }
- else if (successful_responses == 1)
- {
- // We got something else back as the first successful response, it probably is
- // the response to the packet we actually wanted, so copy it over if this
- // is the first success and continue to try to get the qEcho response
- packet = echo_response;
- got_actual_response = true;
- }
- }
- else if (echo_packet_result == PacketResult::ErrorReplyTimeout)
- continue; // Packet timed out, continue waiting for a response
- else
- break; // Something else went wrong getting the packet back, we failed and are done trying
- }
- }
-
- // We weren't able to sync back up with the server, we must abort otherwise
- // all responses might not be from the right packets...
- if (sync_success)
- {
- // We timed out, but were able to recover
- if (got_actual_response)
- {
- // We initially timed out, but we did get a response that came in before the successful
- // reply to our qEcho packet, so lets say everything is fine...
- return PacketResult::Success;
- }
- }
- else
- {
- disconnected = true;
- Disconnect();
- }
+ bool timed_out = false;
+ bool disconnected = false;
+ while (IsConnected() && !timed_out) {
+ lldb::ConnectionStatus status = eConnectionStatusNoConnection;
+ size_t bytes_read = Read(buffer, sizeof(buffer), timeout, status, &error);
+
+ if (log)
+ log->Printf("%s: Read (buffer, (sizeof(buffer), timeout = %ld us, "
+ "status = %s, error = %s) => bytes_read = %" PRIu64,
+ LLVM_PRETTY_FUNCTION, long(timeout ? timeout->count() : -1),
+ Communication::ConnectionStatusAsCString(status),
+ error.AsCString(), (uint64_t)bytes_read);
+
+ if (bytes_read > 0) {
+ if (CheckForPacket(buffer, bytes_read, packet) != PacketType::Invalid)
+ return PacketResult::Success;
+ } else {
+ switch (status) {
+ case eConnectionStatusTimedOut:
+ case eConnectionStatusInterrupted:
+ if (sync_on_timeout) {
+ //------------------------------------------------------------------
+ /// Sync the remote GDB server and make sure we get a response that
+ /// corresponds to what we send.
+ ///
+ /// Sends a "qEcho" packet and makes sure it gets the exact packet
+ /// echoed back. If the qEcho packet isn't supported, we send a qC
+ /// packet and make sure we get a valid thread ID back. We use the
+ /// "qC" packet since its response if very unique: is responds with
+ /// "QC%x" where %x is the thread ID of the current thread. This
+ /// makes the response unique enough from other packet responses to
+ /// ensure we are back on track.
+ ///
+ /// This packet is needed after we time out sending a packet so we
+ /// can ensure that we are getting the response for the packet we
+ /// are sending. There are no sequence IDs in the GDB remote
+ /// protocol (there used to be, but they are not supported anymore)
+ /// so if you timeout sending packet "abc", you might then send
+ /// packet "cde" and get the response for the previous "abc" packet.
+ /// Many responses are "OK" or "" (unsupported) or "EXX" (error) so
+ /// many responses for packets can look like responses for other
+ /// packets. So if we timeout, we need to ensure that we can get
+ /// back on track. If we can't get back on track, we must
+ /// disconnect.
+ //------------------------------------------------------------------
+ bool sync_success = false;
+ bool got_actual_response = false;
+ // We timed out, we need to sync back up with the
+ char echo_packet[32];
+ int echo_packet_len = 0;
+ RegularExpression response_regex;
+
+ if (m_supports_qEcho == eLazyBoolYes) {
+ echo_packet_len = ::snprintf(echo_packet, sizeof(echo_packet),
+ "qEcho:%u", ++m_echo_number);
+ std::string regex_str = "^";
+ regex_str += echo_packet;
+ regex_str += "$";
+ response_regex.Compile(regex_str);
+ } else {
+ echo_packet_len =
+ ::snprintf(echo_packet, sizeof(echo_packet), "qC");
+ response_regex.Compile(llvm::StringRef("^QC[0-9A-Fa-f]+$"));
+ }
+
+ PacketResult echo_packet_result =
+ SendPacketNoLock(llvm::StringRef(echo_packet, echo_packet_len));
+ if (echo_packet_result == PacketResult::Success) {
+ const uint32_t max_retries = 3;
+ uint32_t successful_responses = 0;
+ for (uint32_t i = 0; i < max_retries; ++i) {
+ StringExtractorGDBRemote echo_response;
+ echo_packet_result =
+ WaitForPacketNoLock(echo_response, timeout, false);
+ if (echo_packet_result == PacketResult::Success) {
+ ++successful_responses;
+ if (response_regex.Execute(echo_response.GetStringRef())) {
+ sync_success = true;
+ break;
+ } else if (successful_responses == 1) {
+ // We got something else back as the first successful
+ // response, it probably is
+ // the response to the packet we actually wanted, so copy it
+ // over if this
+ // is the first success and continue to try to get the qEcho
+ // response
+ packet = echo_response;
+ got_actual_response = true;
}
- timed_out = true;
- break;
- case eConnectionStatusSuccess:
- //printf ("status = success but error = %s\n", error.AsCString("<invalid>"));
- break;
-
- case eConnectionStatusEndOfFile:
- case eConnectionStatusNoConnection:
- case eConnectionStatusLostConnection:
- case eConnectionStatusError:
- disconnected = true;
- Disconnect();
- break;
+ } else if (echo_packet_result == PacketResult::ErrorReplyTimeout)
+ continue; // Packet timed out, continue waiting for a response
+ else
+ break; // Something else went wrong getting the packet back, we
+ // failed and are done trying
}
+ }
+
+ // We weren't able to sync back up with the server, we must abort
+ // otherwise
+ // all responses might not be from the right packets...
+ if (sync_success) {
+ // We timed out, but were able to recover
+ if (got_actual_response) {
+ // We initially timed out, but we did get a response that came in
+ // before the successful
+ // reply to our qEcho packet, so lets say everything is fine...
+ return PacketResult::Success;
+ }
+ } else {
+ disconnected = true;
+ Disconnect();
+ }
}
+ timed_out = true;
+ break;
+ case eConnectionStatusSuccess:
+ // printf ("status = success but error = %s\n",
+ // error.AsCString("<invalid>"));
+ break;
+
+ case eConnectionStatusEndOfFile:
+ case eConnectionStatusNoConnection:
+ case eConnectionStatusLostConnection:
+ case eConnectionStatusError:
+ disconnected = true;
+ Disconnect();
+ break;
+ }
}
- packet.Clear ();
- if (disconnected)
- return PacketResult::ErrorDisconnected;
- if (timed_out)
- return PacketResult::ErrorReplyTimeout;
- else
- return PacketResult::ErrorReplyFailed;
+ }
+ packet.Clear();
+ if (disconnected)
+ return PacketResult::ErrorDisconnected;
+ if (timed_out)
+ return PacketResult::ErrorReplyTimeout;
+ else
+ return PacketResult::ErrorReplyFailed;
}
-bool
-GDBRemoteCommunication::DecompressPacket ()
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
-
- if (!CompressionIsEnabled())
- return true;
-
- size_t pkt_size = m_bytes.size();
-
- // Smallest possible compressed packet is $N#00 - an uncompressed empty reply, most commonly indicating
- // an unsupported packet. Anything less than 5 characters, it's definitely not a compressed packet.
- if (pkt_size < 5)
- return true;
-
- if (m_bytes[0] != '$' && m_bytes[0] != '%')
- return true;
- if (m_bytes[1] != 'C' && m_bytes[1] != 'N')
- return true;
-
- size_t hash_mark_idx = m_bytes.find ('#');
- if (hash_mark_idx == std::string::npos)
- return true;
- if (hash_mark_idx + 2 >= m_bytes.size())
- return true;
-
- if (!::isxdigit (m_bytes[hash_mark_idx + 1]) || !::isxdigit (m_bytes[hash_mark_idx + 2]))
- return true;
-
- size_t content_length = pkt_size - 5; // not counting '$', 'C' | 'N', '#', & the two hex checksum chars
- size_t content_start = 2; // The first character of the compressed/not-compressed text of the packet
- size_t checksum_idx = hash_mark_idx + 1; // The first character of the two hex checksum characters
-
- // Normally size_of_first_packet == m_bytes.size() but m_bytes may contain multiple packets.
- // size_of_first_packet is the size of the initial packet which we'll replace with the decompressed
- // version of, leaving the rest of m_bytes unmodified.
- size_t size_of_first_packet = hash_mark_idx + 3;
-
- // Compressed packets ("$C") start with a base10 number which is the size of the uncompressed payload,
- // then a : and then the compressed data. e.g. $C1024:<binary>#00
- // Update content_start and content_length to only include the <binary> part of the packet.
-
- uint64_t decompressed_bufsize = ULONG_MAX;
- if (m_bytes[1] == 'C')
- {
- size_t i = content_start;
- while (i < hash_mark_idx && isdigit(m_bytes[i]))
- i++;
- if (i < hash_mark_idx && m_bytes[i] == ':')
- {
- i++;
- content_start = i;
- content_length = hash_mark_idx - content_start;
- std::string bufsize_str (m_bytes.data() + 2, i - 2 - 1);
- errno = 0;
- decompressed_bufsize = ::strtoul (bufsize_str.c_str(), NULL, 10);
- if (errno != 0 || decompressed_bufsize == ULONG_MAX)
- {
- m_bytes.erase (0, size_of_first_packet);
- return false;
- }
- }
- }
+bool GDBRemoteCommunication::DecompressPacket() {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
- if (GetSendAcks ())
- {
- char packet_checksum_cstr[3];
- packet_checksum_cstr[0] = m_bytes[checksum_idx];
- packet_checksum_cstr[1] = m_bytes[checksum_idx + 1];
- packet_checksum_cstr[2] = '\0';
- long packet_checksum = strtol (packet_checksum_cstr, NULL, 16);
-
- long actual_checksum = CalculcateChecksum (m_bytes.data() + 1, hash_mark_idx - 1);
- bool success = packet_checksum == actual_checksum;
- if (!success)
- {
- if (log)
- log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x",
- (int)(pkt_size),
- m_bytes.c_str(),
- (uint8_t)packet_checksum,
- (uint8_t)actual_checksum);
- }
- // Send the ack or nack if needed
- if (!success)
- {
- SendNack();
- m_bytes.erase (0, size_of_first_packet);
- return false;
- }
- else
- {
- SendAck();
- }
- }
+ if (!CompressionIsEnabled())
+ return true;
- if (m_bytes[1] == 'N')
- {
- // This packet was not compressed -- delete the 'N' character at the
- // start and the packet may be processed as-is.
- m_bytes.erase(1, 1);
- return true;
- }
+ size_t pkt_size = m_bytes.size();
- // Reverse the gdb-remote binary escaping that was done to the compressed text to
- // guard characters like '$', '#', '}', etc.
- std::vector<uint8_t> unescaped_content;
- unescaped_content.reserve (content_length);
- size_t i = content_start;
- while (i < hash_mark_idx)
- {
- if (m_bytes[i] == '}')
- {
- i++;
- unescaped_content.push_back (m_bytes[i] ^ 0x20);
- }
- else
- {
- unescaped_content.push_back (m_bytes[i]);
- }
- i++;
- }
+ // Smallest possible compressed packet is $N#00 - an uncompressed empty reply,
+ // most commonly indicating
+ // an unsupported packet. Anything less than 5 characters, it's definitely
+ // not a compressed packet.
+ if (pkt_size < 5)
+ return true;
- uint8_t *decompressed_buffer = nullptr;
- size_t decompressed_bytes = 0;
+ if (m_bytes[0] != '$' && m_bytes[0] != '%')
+ return true;
+ if (m_bytes[1] != 'C' && m_bytes[1] != 'N')
+ return true;
- if (decompressed_bufsize != ULONG_MAX)
- {
- decompressed_buffer = (uint8_t *) malloc (decompressed_bufsize + 1);
- if (decompressed_buffer == nullptr)
- {
- m_bytes.erase (0, size_of_first_packet);
- return false;
- }
+ size_t hash_mark_idx = m_bytes.find('#');
+ if (hash_mark_idx == std::string::npos)
+ return true;
+ if (hash_mark_idx + 2 >= m_bytes.size())
+ return true;
- }
+ if (!::isxdigit(m_bytes[hash_mark_idx + 1]) ||
+ !::isxdigit(m_bytes[hash_mark_idx + 2]))
+ return true;
-#if defined (HAVE_LIBCOMPRESSION)
- // libcompression is weak linked so check that compression_decode_buffer() is available
- if (compression_decode_buffer != NULL &&
- (m_compression_type == CompressionType::ZlibDeflate
- || m_compression_type == CompressionType::LZFSE
- || m_compression_type == CompressionType::LZ4))
- {
- compression_algorithm compression_type;
- if (m_compression_type == CompressionType::ZlibDeflate)
- compression_type = COMPRESSION_ZLIB;
- else if (m_compression_type == CompressionType::LZFSE)
- compression_type = COMPRESSION_LZFSE;
- else if (m_compression_type == CompressionType::LZ4)
- compression_type = COMPRESSION_LZ4_RAW;
- else if (m_compression_type == CompressionType::LZMA)
- compression_type = COMPRESSION_LZMA;
-
-
- // If we have the expected size of the decompressed payload, we can allocate
- // the right-sized buffer and do it. If we don't have that information, we'll
- // need to try decoding into a big buffer and if the buffer wasn't big enough,
- // increase it and try again.
-
- if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr)
- {
- decompressed_bytes = compression_decode_buffer (decompressed_buffer, decompressed_bufsize + 10 ,
- (uint8_t*) unescaped_content.data(),
- unescaped_content.size(),
- NULL,
- compression_type);
- }
+ size_t content_length =
+ pkt_size -
+ 5; // not counting '$', 'C' | 'N', '#', & the two hex checksum chars
+ size_t content_start = 2; // The first character of the
+ // compressed/not-compressed text of the packet
+ size_t checksum_idx =
+ hash_mark_idx +
+ 1; // The first character of the two hex checksum characters
+
+ // Normally size_of_first_packet == m_bytes.size() but m_bytes may contain
+ // multiple packets.
+ // size_of_first_packet is the size of the initial packet which we'll replace
+ // with the decompressed
+ // version of, leaving the rest of m_bytes unmodified.
+ size_t size_of_first_packet = hash_mark_idx + 3;
+
+ // Compressed packets ("$C") start with a base10 number which is the size of
+ // the uncompressed payload,
+ // then a : and then the compressed data. e.g. $C1024:<binary>#00
+ // Update content_start and content_length to only include the <binary> part
+ // of the packet.
+
+ uint64_t decompressed_bufsize = ULONG_MAX;
+ if (m_bytes[1] == 'C') {
+ size_t i = content_start;
+ while (i < hash_mark_idx && isdigit(m_bytes[i]))
+ i++;
+ if (i < hash_mark_idx && m_bytes[i] == ':') {
+ i++;
+ content_start = i;
+ content_length = hash_mark_idx - content_start;
+ std::string bufsize_str(m_bytes.data() + 2, i - 2 - 1);
+ errno = 0;
+ decompressed_bufsize = ::strtoul(bufsize_str.c_str(), NULL, 10);
+ if (errno != 0 || decompressed_bufsize == ULONG_MAX) {
+ m_bytes.erase(0, size_of_first_packet);
+ return false;
+ }
}
-#endif
-
-#if defined (HAVE_LIBZ)
- if (decompressed_bytes == 0
- && decompressed_bufsize != ULONG_MAX
- && decompressed_buffer != nullptr
- && m_compression_type == CompressionType::ZlibDeflate)
- {
- z_stream stream;
- memset (&stream, 0, sizeof (z_stream));
- stream.next_in = (Bytef *) unescaped_content.data();
- stream.avail_in = (uInt) unescaped_content.size();
- stream.total_in = 0;
- stream.next_out = (Bytef *) decompressed_buffer;
- stream.avail_out = decompressed_bufsize;
- stream.total_out = 0;
- stream.zalloc = Z_NULL;
- stream.zfree = Z_NULL;
- stream.opaque = Z_NULL;
-
- if (inflateInit2 (&stream, -15) == Z_OK)
- {
- int status = inflate (&stream, Z_NO_FLUSH);
- inflateEnd (&stream);
- if (status == Z_STREAM_END)
- {
- decompressed_bytes = stream.total_out;
- }
- }
+ }
+
+ if (GetSendAcks()) {
+ char packet_checksum_cstr[3];
+ packet_checksum_cstr[0] = m_bytes[checksum_idx];
+ packet_checksum_cstr[1] = m_bytes[checksum_idx + 1];
+ packet_checksum_cstr[2] = '\0';
+ long packet_checksum = strtol(packet_checksum_cstr, NULL, 16);
+
+ long actual_checksum = CalculcateChecksum(
+ llvm::StringRef(m_bytes).substr(1, hash_mark_idx - 1));
+ bool success = packet_checksum == actual_checksum;
+ if (!success) {
+ if (log)
+ log->Printf(
+ "error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x",
+ (int)(pkt_size), m_bytes.c_str(), (uint8_t)packet_checksum,
+ (uint8_t)actual_checksum);
}
-#endif
+ // Send the ack or nack if needed
+ if (!success) {
+ SendNack();
+ m_bytes.erase(0, size_of_first_packet);
+ return false;
+ } else {
+ SendAck();
+ }
+ }
- if (decompressed_bytes == 0 || decompressed_buffer == nullptr)
- {
- if (decompressed_buffer)
- free (decompressed_buffer);
- m_bytes.erase (0, size_of_first_packet);
- return false;
+ if (m_bytes[1] == 'N') {
+ // This packet was not compressed -- delete the 'N' character at the
+ // start and the packet may be processed as-is.
+ m_bytes.erase(1, 1);
+ return true;
+ }
+
+ // Reverse the gdb-remote binary escaping that was done to the compressed text
+ // to
+ // guard characters like '$', '#', '}', etc.
+ std::vector<uint8_t> unescaped_content;
+ unescaped_content.reserve(content_length);
+ size_t i = content_start;
+ while (i < hash_mark_idx) {
+ if (m_bytes[i] == '}') {
+ i++;
+ unescaped_content.push_back(m_bytes[i] ^ 0x20);
+ } else {
+ unescaped_content.push_back(m_bytes[i]);
}
+ i++;
+ }
+
+ uint8_t *decompressed_buffer = nullptr;
+ size_t decompressed_bytes = 0;
- std::string new_packet;
- new_packet.reserve (decompressed_bytes + 6);
- new_packet.push_back (m_bytes[0]);
- new_packet.append ((const char *) decompressed_buffer, decompressed_bytes);
- new_packet.push_back ('#');
- if (GetSendAcks ())
- {
- uint8_t decompressed_checksum = CalculcateChecksum ((const char *) decompressed_buffer, decompressed_bytes);
- char decompressed_checksum_str[3];
- snprintf (decompressed_checksum_str, 3, "%02x", decompressed_checksum);
- new_packet.append (decompressed_checksum_str);
+ if (decompressed_bufsize != ULONG_MAX) {
+ decompressed_buffer = (uint8_t *)malloc(decompressed_bufsize + 1);
+ if (decompressed_buffer == nullptr) {
+ m_bytes.erase(0, size_of_first_packet);
+ return false;
}
- else
- {
- new_packet.push_back ('0');
- new_packet.push_back ('0');
+ }
+
+#if defined(HAVE_LIBCOMPRESSION)
+ // libcompression is weak linked so check that compression_decode_buffer() is
+ // available
+ if (compression_decode_buffer != NULL &&
+ (m_compression_type == CompressionType::ZlibDeflate ||
+ m_compression_type == CompressionType::LZFSE ||
+ m_compression_type == CompressionType::LZ4)) {
+ compression_algorithm compression_type;
+ if (m_compression_type == CompressionType::ZlibDeflate)
+ compression_type = COMPRESSION_ZLIB;
+ else if (m_compression_type == CompressionType::LZFSE)
+ compression_type = COMPRESSION_LZFSE;
+ else if (m_compression_type == CompressionType::LZ4)
+ compression_type = COMPRESSION_LZ4_RAW;
+ else if (m_compression_type == CompressionType::LZMA)
+ compression_type = COMPRESSION_LZMA;
+
+ // If we have the expected size of the decompressed payload, we can allocate
+ // the right-sized buffer and do it. If we don't have that information,
+ // we'll
+ // need to try decoding into a big buffer and if the buffer wasn't big
+ // enough,
+ // increase it and try again.
+
+ if (decompressed_bufsize != ULONG_MAX && decompressed_buffer != nullptr) {
+ decompressed_bytes = compression_decode_buffer(
+ decompressed_buffer, decompressed_bufsize + 10,
+ (uint8_t *)unescaped_content.data(), unescaped_content.size(), NULL,
+ compression_type);
}
+ }
+#endif
- m_bytes.replace (0, size_of_first_packet, new_packet.data(), new_packet.size());
+#if defined(HAVE_LIBZ)
+ if (decompressed_bytes == 0 && decompressed_bufsize != ULONG_MAX &&
+ decompressed_buffer != nullptr &&
+ m_compression_type == CompressionType::ZlibDeflate) {
+ z_stream stream;
+ memset(&stream, 0, sizeof(z_stream));
+ stream.next_in = (Bytef *)unescaped_content.data();
+ stream.avail_in = (uInt)unescaped_content.size();
+ stream.total_in = 0;
+ stream.next_out = (Bytef *)decompressed_buffer;
+ stream.avail_out = decompressed_bufsize;
+ stream.total_out = 0;
+ stream.zalloc = Z_NULL;
+ stream.zfree = Z_NULL;
+ stream.opaque = Z_NULL;
+
+ if (inflateInit2(&stream, -15) == Z_OK) {
+ int status = inflate(&stream, Z_NO_FLUSH);
+ inflateEnd(&stream);
+ if (status == Z_STREAM_END) {
+ decompressed_bytes = stream.total_out;
+ }
+ }
+ }
+#endif
- free (decompressed_buffer);
- return true;
+ if (decompressed_bytes == 0 || decompressed_buffer == nullptr) {
+ if (decompressed_buffer)
+ free(decompressed_buffer);
+ m_bytes.erase(0, size_of_first_packet);
+ return false;
+ }
+
+ std::string new_packet;
+ new_packet.reserve(decompressed_bytes + 6);
+ new_packet.push_back(m_bytes[0]);
+ new_packet.append((const char *)decompressed_buffer, decompressed_bytes);
+ new_packet.push_back('#');
+ if (GetSendAcks()) {
+ uint8_t decompressed_checksum = CalculcateChecksum(
+ llvm::StringRef((const char *)decompressed_buffer, decompressed_bytes));
+ char decompressed_checksum_str[3];
+ snprintf(decompressed_checksum_str, 3, "%02x", decompressed_checksum);
+ new_packet.append(decompressed_checksum_str);
+ } else {
+ new_packet.push_back('0');
+ new_packet.push_back('0');
+ }
+
+ m_bytes.replace(0, size_of_first_packet, new_packet.data(),
+ new_packet.size());
+
+ free(decompressed_buffer);
+ return true;
}
GDBRemoteCommunication::PacketType
-GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, StringExtractorGDBRemote &packet)
-{
- // Put the packet data into the buffer in a thread safe fashion
- std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex);
-
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
-
- if (src && src_len > 0)
- {
- if (log && log->GetVerbose())
- {
- StreamString s;
- log->Printf ("GDBRemoteCommunication::%s adding %u bytes: %.*s",
- __FUNCTION__,
- (uint32_t)src_len,
- (uint32_t)src_len,
- src);
- }
- m_bytes.append ((const char *)src, src_len);
+GDBRemoteCommunication::CheckForPacket(const uint8_t *src, size_t src_len,
+ StringExtractorGDBRemote &packet) {
+ // Put the packet data into the buffer in a thread safe fashion
+ std::lock_guard<std::recursive_mutex> guard(m_bytes_mutex);
+
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
+
+ if (src && src_len > 0) {
+ if (log && log->GetVerbose()) {
+ StreamString s;
+ log->Printf("GDBRemoteCommunication::%s adding %u bytes: %.*s",
+ __FUNCTION__, (uint32_t)src_len, (uint32_t)src_len, src);
+ }
+ m_bytes.append((const char *)src, src_len);
+ }
+
+ bool isNotifyPacket = false;
+
+ // Parse up the packets into gdb remote packets
+ if (!m_bytes.empty()) {
+ // end_idx must be one past the last valid packet byte. Start
+ // it off with an invalid value that is the same as the current
+ // index.
+ size_t content_start = 0;
+ size_t content_length = 0;
+ size_t total_length = 0;
+ size_t checksum_idx = std::string::npos;
+
+ // Size of packet before it is decompressed, for logging purposes
+ size_t original_packet_size = m_bytes.size();
+ if (CompressionIsEnabled()) {
+ if (DecompressPacket() == false) {
+ packet.Clear();
+ return GDBRemoteCommunication::PacketType::Standard;
+ }
}
- bool isNotifyPacket = false;
-
- // Parse up the packets into gdb remote packets
- if (!m_bytes.empty())
- {
- // end_idx must be one past the last valid packet byte. Start
- // it off with an invalid value that is the same as the current
- // index.
- size_t content_start = 0;
- size_t content_length = 0;
- size_t total_length = 0;
- size_t checksum_idx = std::string::npos;
-
- // Size of packet before it is decompressed, for logging purposes
- size_t original_packet_size = m_bytes.size();
- if (CompressionIsEnabled())
- {
- if (DecompressPacket() == false)
- {
- packet.Clear();
- return GDBRemoteCommunication::PacketType::Standard;
- }
+ switch (m_bytes[0]) {
+ case '+': // Look for ack
+ case '-': // Look for cancel
+ case '\x03': // ^C to halt target
+ content_length = total_length = 1; // The command is one byte long...
+ break;
+
+ case '%': // Async notify packet
+ isNotifyPacket = true;
+ LLVM_FALLTHROUGH;
+
+ case '$':
+ // Look for a standard gdb packet?
+ {
+ size_t hash_pos = m_bytes.find('#');
+ if (hash_pos != std::string::npos) {
+ if (hash_pos + 2 < m_bytes.size()) {
+ checksum_idx = hash_pos + 1;
+ // Skip the dollar sign
+ content_start = 1;
+ // Don't include the # in the content or the $ in the content length
+ content_length = hash_pos - 1;
+
+ total_length =
+ hash_pos + 3; // Skip the # and the two hex checksum bytes
+ } else {
+ // Checksum bytes aren't all here yet
+ content_length = std::string::npos;
+ }
}
-
- switch (m_bytes[0])
- {
- case '+': // Look for ack
- case '-': // Look for cancel
- case '\x03': // ^C to halt target
- content_length = total_length = 1; // The command is one byte long...
- break;
-
- case '%': // Async notify packet
- isNotifyPacket = true;
- LLVM_FALLTHROUGH;
-
- case '$':
- // Look for a standard gdb packet?
- {
- size_t hash_pos = m_bytes.find('#');
- if (hash_pos != std::string::npos)
- {
- if (hash_pos + 2 < m_bytes.size())
- {
- checksum_idx = hash_pos + 1;
- // Skip the dollar sign
- content_start = 1;
- // Don't include the # in the content or the $ in the content length
- content_length = hash_pos - 1;
-
- total_length = hash_pos + 3; // Skip the # and the two hex checksum bytes
- }
- else
- {
- // Checksum bytes aren't all here yet
- content_length = std::string::npos;
- }
- }
- }
- break;
-
- default:
- {
- // We have an unexpected byte and we need to flush all bad
- // data that is in m_bytes, so we need to find the first
- // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt),
- // or '$' character (start of packet header) or of course,
- // the end of the data in m_bytes...
- const size_t bytes_len = m_bytes.size();
- bool done = false;
- uint32_t idx;
- for (idx = 1; !done && idx < bytes_len; ++idx)
- {
- switch (m_bytes[idx])
- {
- case '+':
- case '-':
- case '\x03':
- case '%':
- case '$':
- done = true;
- break;
-
- default:
- break;
- }
- }
- if (log)
- log->Printf ("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'",
- __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str());
- m_bytes.erase(0, idx - 1);
- }
- break;
+ }
+ break;
+
+ default: {
+ // We have an unexpected byte and we need to flush all bad
+ // data that is in m_bytes, so we need to find the first
+ // byte that is a '+' (ACK), '-' (NACK), \x03 (CTRL+C interrupt),
+ // or '$' character (start of packet header) or of course,
+ // the end of the data in m_bytes...
+ const size_t bytes_len = m_bytes.size();
+ bool done = false;
+ uint32_t idx;
+ for (idx = 1; !done && idx < bytes_len; ++idx) {
+ switch (m_bytes[idx]) {
+ case '+':
+ case '-':
+ case '\x03':
+ case '%':
+ case '$':
+ done = true;
+ break;
+
+ default:
+ break;
}
+ }
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s tossing %u junk bytes: '%.*s'",
+ __FUNCTION__, idx - 1, idx - 1, m_bytes.c_str());
+ m_bytes.erase(0, idx - 1);
+ } break;
+ }
- if (content_length == std::string::npos)
- {
- packet.Clear();
- return GDBRemoteCommunication::PacketType::Invalid;
- }
- else if (total_length > 0)
- {
-
- // We have a valid packet...
- assert (content_length <= m_bytes.size());
- assert (total_length <= m_bytes.size());
- assert (content_length <= total_length);
- size_t content_end = content_start + content_length;
-
- bool success = true;
- std::string &packet_str = packet.GetStringRef();
- if (log)
- {
- // If logging was just enabled and we have history, then dump out what
- // we have to the log so we get the historical context. The Dump() call that
- // logs all of the packet will set a boolean so that we don't dump this more
- // than once
- if (!m_history.DidDumpToLog ())
- m_history.Dump (log);
-
- bool binary = false;
- // Only detect binary for packets that start with a '$' and have a '#CC' checksum
- if (m_bytes[0] == '$' && total_length > 4)
- {
- for (size_t i=0; !binary && i<total_length; ++i)
- {
- if (isprint (m_bytes[i]) == 0 && isspace (m_bytes[i]) == 0)
- {
- binary = true;
- }
- }
- }
- if (binary)
- {
- StreamString strm;
- // Packet header...
- if (CompressionIsEnabled())
- strm.Printf("<%4" PRIu64 ":%" PRIu64 "> read packet: %c", (uint64_t) original_packet_size, (uint64_t)total_length, m_bytes[0]);
- else
- strm.Printf("<%4" PRIu64 "> read packet: %c", (uint64_t)total_length, m_bytes[0]);
- for (size_t i=content_start; i<content_end; ++i)
- {
- // Remove binary escaped bytes when displaying the packet...
- const char ch = m_bytes[i];
- if (ch == 0x7d)
- {
- // 0x7d is the escape character. The next character is to
- // be XOR'd with 0x20.
- const char escapee = m_bytes[++i] ^ 0x20;
- strm.Printf("%2.2x", escapee);
- }
- else
- {
- strm.Printf("%2.2x", (uint8_t)ch);
- }
- }
- // Packet footer...
- strm.Printf("%c%c%c", m_bytes[total_length-3], m_bytes[total_length-2], m_bytes[total_length-1]);
- log->PutCString(strm.GetString().c_str());
- }
- else
- {
- if (CompressionIsEnabled())
- log->Printf("<%4" PRIu64 ":%" PRIu64 "> read packet: %.*s", (uint64_t) original_packet_size, (uint64_t)total_length, (int)(total_length), m_bytes.c_str());
- else
- log->Printf("<%4" PRIu64 "> read packet: %.*s", (uint64_t)total_length, (int)(total_length), m_bytes.c_str());
- }
+ if (content_length == std::string::npos) {
+ packet.Clear();
+ return GDBRemoteCommunication::PacketType::Invalid;
+ } else if (total_length > 0) {
+
+ // We have a valid packet...
+ assert(content_length <= m_bytes.size());
+ assert(total_length <= m_bytes.size());
+ assert(content_length <= total_length);
+ size_t content_end = content_start + content_length;
+
+ bool success = true;
+ std::string &packet_str = packet.GetStringRef();
+ if (log) {
+ // If logging was just enabled and we have history, then dump out what
+ // we have to the log so we get the historical context. The Dump() call
+ // that
+ // logs all of the packet will set a boolean so that we don't dump this
+ // more
+ // than once
+ if (!m_history.DidDumpToLog())
+ m_history.Dump(log);
+
+ bool binary = false;
+ // Only detect binary for packets that start with a '$' and have a '#CC'
+ // checksum
+ if (m_bytes[0] == '$' && total_length > 4) {
+ for (size_t i = 0; !binary && i < total_length; ++i) {
+ if (isprint(m_bytes[i]) == 0 && isspace(m_bytes[i]) == 0) {
+ binary = true;
}
-
- m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length);
-
- // Clear packet_str in case there is some existing data in it.
- packet_str.clear();
- // Copy the packet from m_bytes to packet_str expanding the
- // run-length encoding in the process.
- // Reserve enough byte for the most common case (no RLE used)
- packet_str.reserve(m_bytes.length());
- for (std::string::const_iterator c = m_bytes.begin() + content_start; c != m_bytes.begin() + content_end; ++c)
- {
- if (*c == '*')
- {
- // '*' indicates RLE. Next character will give us the
- // repeat count and previous character is what is to be
- // repeated.
- char char_to_repeat = packet_str.back();
- // Number of time the previous character is repeated
- int repeat_count = *++c + 3 - ' ';
- // We have the char_to_repeat and repeat_count. Now push
- // it in the packet.
- for (int i = 0; i < repeat_count; ++i)
- packet_str.push_back(char_to_repeat);
- }
- else if (*c == 0x7d)
- {
- // 0x7d is the escape character. The next character is to
- // be XOR'd with 0x20.
- char escapee = *++c ^ 0x20;
- packet_str.push_back(escapee);
- }
- else
- {
- packet_str.push_back(*c);
- }
+ }
+ }
+ if (binary) {
+ StreamString strm;
+ // Packet header...
+ if (CompressionIsEnabled())
+ strm.Printf("<%4" PRIu64 ":%" PRIu64 "> read packet: %c",
+ (uint64_t)original_packet_size, (uint64_t)total_length,
+ m_bytes[0]);
+ else
+ strm.Printf("<%4" PRIu64 "> read packet: %c",
+ (uint64_t)total_length, m_bytes[0]);
+ for (size_t i = content_start; i < content_end; ++i) {
+ // Remove binary escaped bytes when displaying the packet...
+ const char ch = m_bytes[i];
+ if (ch == 0x7d) {
+ // 0x7d is the escape character. The next character is to
+ // be XOR'd with 0x20.
+ const char escapee = m_bytes[++i] ^ 0x20;
+ strm.Printf("%2.2x", escapee);
+ } else {
+ strm.Printf("%2.2x", (uint8_t)ch);
}
-
- if (m_bytes[0] == '$' || m_bytes[0] == '%')
- {
- assert (checksum_idx < m_bytes.size());
- if (::isxdigit (m_bytes[checksum_idx+0]) ||
- ::isxdigit (m_bytes[checksum_idx+1]))
- {
- if (GetSendAcks ())
- {
- const char *packet_checksum_cstr = &m_bytes[checksum_idx];
- char packet_checksum = strtol (packet_checksum_cstr, NULL, 16);
- char actual_checksum = CalculcateChecksum (packet_str.c_str(), packet_str.size());
- success = packet_checksum == actual_checksum;
- if (!success)
- {
- if (log)
- log->Printf ("error: checksum mismatch: %.*s expected 0x%2.2x, got 0x%2.2x",
- (int)(total_length),
- m_bytes.c_str(),
- (uint8_t)packet_checksum,
- (uint8_t)actual_checksum);
- }
- // Send the ack or nack if needed
- if (!success)
- SendNack();
- else
- SendAck();
- }
- }
- else
- {
- success = false;
- if (log)
- log->Printf ("error: invalid checksum in packet: '%s'\n", m_bytes.c_str());
- }
+ }
+ // Packet footer...
+ strm.Printf("%c%c%c", m_bytes[total_length - 3],
+ m_bytes[total_length - 2], m_bytes[total_length - 1]);
+ log->PutString(strm.GetString());
+ } else {
+ if (CompressionIsEnabled())
+ log->Printf("<%4" PRIu64 ":%" PRIu64 "> read packet: %.*s",
+ (uint64_t)original_packet_size, (uint64_t)total_length,
+ (int)(total_length), m_bytes.c_str());
+ else
+ log->Printf("<%4" PRIu64 "> read packet: %.*s",
+ (uint64_t)total_length, (int)(total_length),
+ m_bytes.c_str());
+ }
+ }
+
+ m_history.AddPacket(m_bytes, total_length, History::ePacketTypeRecv,
+ total_length);
+
+ // Clear packet_str in case there is some existing data in it.
+ packet_str.clear();
+ // Copy the packet from m_bytes to packet_str expanding the
+ // run-length encoding in the process.
+ // Reserve enough byte for the most common case (no RLE used)
+ packet_str.reserve(m_bytes.length());
+ for (std::string::const_iterator c = m_bytes.begin() + content_start;
+ c != m_bytes.begin() + content_end; ++c) {
+ if (*c == '*') {
+ // '*' indicates RLE. Next character will give us the
+ // repeat count and previous character is what is to be
+ // repeated.
+ char char_to_repeat = packet_str.back();
+ // Number of time the previous character is repeated
+ int repeat_count = *++c + 3 - ' ';
+ // We have the char_to_repeat and repeat_count. Now push
+ // it in the packet.
+ for (int i = 0; i < repeat_count; ++i)
+ packet_str.push_back(char_to_repeat);
+ } else if (*c == 0x7d) {
+ // 0x7d is the escape character. The next character is to
+ // be XOR'd with 0x20.
+ char escapee = *++c ^ 0x20;
+ packet_str.push_back(escapee);
+ } else {
+ packet_str.push_back(*c);
+ }
+ }
+
+ if (m_bytes[0] == '$' || m_bytes[0] == '%') {
+ assert(checksum_idx < m_bytes.size());
+ if (::isxdigit(m_bytes[checksum_idx + 0]) ||
+ ::isxdigit(m_bytes[checksum_idx + 1])) {
+ if (GetSendAcks()) {
+ const char *packet_checksum_cstr = &m_bytes[checksum_idx];
+ char packet_checksum = strtol(packet_checksum_cstr, NULL, 16);
+ char actual_checksum = CalculcateChecksum(packet_str);
+ success = packet_checksum == actual_checksum;
+ if (!success) {
+ if (log)
+ log->Printf("error: checksum mismatch: %.*s expected 0x%2.2x, "
+ "got 0x%2.2x",
+ (int)(total_length), m_bytes.c_str(),
+ (uint8_t)packet_checksum, (uint8_t)actual_checksum);
}
-
- m_bytes.erase(0, total_length);
- packet.SetFilePos(0);
-
- if (isNotifyPacket)
- return GDBRemoteCommunication::PacketType::Notify;
+ // Send the ack or nack if needed
+ if (!success)
+ SendNack();
else
- return GDBRemoteCommunication::PacketType::Standard;
+ SendAck();
+ }
+ } else {
+ success = false;
+ if (log)
+ log->Printf("error: invalid checksum in packet: '%s'\n",
+ m_bytes.c_str());
}
+ }
+
+ m_bytes.erase(0, total_length);
+ packet.SetFilePos(0);
+
+ if (isNotifyPacket)
+ return GDBRemoteCommunication::PacketType::Notify;
+ else
+ return GDBRemoteCommunication::PacketType::Standard;
}
- packet.Clear();
- return GDBRemoteCommunication::PacketType::Invalid;
+ }
+ packet.Clear();
+ return GDBRemoteCommunication::PacketType::Invalid;
}
-Error
-GDBRemoteCommunication::StartListenThread (const char *hostname, uint16_t port)
-{
- Error error;
- if (m_listen_thread.IsJoinable())
- {
- error.SetErrorString("listen thread already running");
- }
+Error GDBRemoteCommunication::StartListenThread(const char *hostname,
+ uint16_t port) {
+ Error error;
+ if (m_listen_thread.IsJoinable()) {
+ error.SetErrorString("listen thread already running");
+ } else {
+ char listen_url[512];
+ if (hostname && hostname[0])
+ snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname,
+ port);
else
- {
- char listen_url[512];
- if (hostname && hostname[0])
- snprintf(listen_url, sizeof(listen_url), "listen://%s:%i", hostname, port);
- else
- snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
- m_listen_url = listen_url;
- SetConnection(new ConnectionFileDescriptor());
- m_listen_thread = ThreadLauncher::LaunchThread(listen_url, GDBRemoteCommunication::ListenThread, this, &error);
- }
- return error;
+ snprintf(listen_url, sizeof(listen_url), "listen://%i", port);
+ m_listen_url = listen_url;
+ SetConnection(new ConnectionFileDescriptor());
+ m_listen_thread = ThreadLauncher::LaunchThread(
+ listen_url, GDBRemoteCommunication::ListenThread, this, &error);
+ }
+ return error;
}
-bool
-GDBRemoteCommunication::JoinListenThread ()
-{
- if (m_listen_thread.IsJoinable())
- m_listen_thread.Join(nullptr);
- return true;
+bool GDBRemoteCommunication::JoinListenThread() {
+ if (m_listen_thread.IsJoinable())
+ m_listen_thread.Join(nullptr);
+ return true;
}
lldb::thread_result_t
-GDBRemoteCommunication::ListenThread (lldb::thread_arg_t arg)
-{
- GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg;
- Error error;
- ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)comm->GetConnection ();
-
- if (connection)
- {
- // Do the listen on another thread so we can continue on...
- if (connection->Connect(comm->m_listen_url.c_str(), &error) != eConnectionStatusSuccess)
- comm->SetConnection(NULL);
- }
- return NULL;
+GDBRemoteCommunication::ListenThread(lldb::thread_arg_t arg) {
+ GDBRemoteCommunication *comm = (GDBRemoteCommunication *)arg;
+ Error error;
+ ConnectionFileDescriptor *connection =
+ (ConnectionFileDescriptor *)comm->GetConnection();
+
+ if (connection) {
+ // Do the listen on another thread so we can continue on...
+ if (connection->Connect(comm->m_listen_url.c_str(), &error) !=
+ eConnectionStatusSuccess)
+ comm->SetConnection(NULL);
+ }
+ return NULL;
}
-Error
-GDBRemoteCommunication::StartDebugserverProcess (const char *url,
- Platform *platform,
- ProcessLaunchInfo &launch_info,
- uint16_t *port,
- const Args& inferior_args)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+Error GDBRemoteCommunication::StartDebugserverProcess(
+ const char *url, Platform *platform, ProcessLaunchInfo &launch_info,
+ uint16_t *port, const Args *inferior_args, int pass_comm_fd) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")",
+ __FUNCTION__, url ? url : "<empty>",
+ port ? *port : uint16_t(0));
+
+ Error error;
+ // If we locate debugserver, keep that located version around
+ static FileSpec g_debugserver_file_spec;
+
+ char debugserver_path[PATH_MAX];
+ FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
+
+ // Always check to see if we have an environment override for the path
+ // to the debugserver to use and use it if we do.
+ const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
+ if (env_debugserver_path) {
+ debugserver_file_spec.SetFile(env_debugserver_path, false);
if (log)
- log->Printf ("GDBRemoteCommunication::%s(url=%s, port=%" PRIu16 ")", __FUNCTION__, url ? url : "<empty>", port ? *port : uint16_t(0));
-
- Error error;
- // If we locate debugserver, keep that located version around
- static FileSpec g_debugserver_file_spec;
-
- char debugserver_path[PATH_MAX];
- FileSpec &debugserver_file_spec = launch_info.GetExecutableFile();
-
- // Always check to see if we have an environment override for the path
- // to the debugserver to use and use it if we do.
- const char *env_debugserver_path = getenv("LLDB_DEBUGSERVER_PATH");
- if (env_debugserver_path)
- {
- debugserver_file_spec.SetFile (env_debugserver_path, false);
+ log->Printf("GDBRemoteCommunication::%s() gdb-remote stub exe path set "
+ "from environment variable: %s",
+ __FUNCTION__, env_debugserver_path);
+ } else
+ debugserver_file_spec = g_debugserver_file_spec;
+ bool debugserver_exists = debugserver_file_spec.Exists();
+ if (!debugserver_exists) {
+ // The debugserver binary is in the LLDB.framework/Resources
+ // directory.
+ if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir,
+ debugserver_file_spec)) {
+ debugserver_file_spec.AppendPathComponent(DEBUGSERVER_BASENAME);
+ debugserver_exists = debugserver_file_spec.Exists();
+ if (debugserver_exists) {
if (log)
- log->Printf ("GDBRemoteCommunication::%s() gdb-remote stub exe path set from environment variable: %s", __FUNCTION__, env_debugserver_path);
- }
- else
- debugserver_file_spec = g_debugserver_file_spec;
- bool debugserver_exists = debugserver_file_spec.Exists();
- if (!debugserver_exists)
- {
- // The debugserver binary is in the LLDB.framework/Resources
- // directory.
- if (HostInfo::GetLLDBPath(ePathTypeSupportExecutableDir, debugserver_file_spec))
- {
- debugserver_file_spec.AppendPathComponent (DEBUGSERVER_BASENAME);
- debugserver_exists = debugserver_file_spec.Exists();
- if (debugserver_exists)
- {
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
-
- g_debugserver_file_spec = debugserver_file_spec;
- }
- else
- {
- debugserver_file_spec = platform->LocateExecutable(DEBUGSERVER_BASENAME);
- if (debugserver_file_spec)
- {
- // Platform::LocateExecutable() wouldn't return a path if it doesn't exist
- debugserver_exists = true;
- }
- else
- {
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() could not find gdb-remote stub exe '%s'", __FUNCTION__, debugserver_file_spec.GetPath ().c_str ());
- }
- // Don't cache the platform specific GDB server binary as it could change
- // from platform to platform
- g_debugserver_file_spec.Clear();
- }
+ log->Printf(
+ "GDBRemoteCommunication::%s() found gdb-remote stub exe '%s'",
+ __FUNCTION__, debugserver_file_spec.GetPath().c_str());
+
+ g_debugserver_file_spec = debugserver_file_spec;
+ } else {
+ debugserver_file_spec =
+ platform->LocateExecutable(DEBUGSERVER_BASENAME);
+ if (debugserver_file_spec) {
+ // Platform::LocateExecutable() wouldn't return a path if it doesn't
+ // exist
+ debugserver_exists = true;
+ } else {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() could not find "
+ "gdb-remote stub exe '%s'",
+ __FUNCTION__, debugserver_file_spec.GetPath().c_str());
}
+ // Don't cache the platform specific GDB server binary as it could
+ // change
+ // from platform to platform
+ g_debugserver_file_spec.Clear();
+ }
}
-
- if (debugserver_exists)
- {
- debugserver_file_spec.GetPath (debugserver_path, sizeof(debugserver_path));
+ }
+
+ if (debugserver_exists) {
+ debugserver_file_spec.GetPath(debugserver_path, sizeof(debugserver_path));
- Args &debugserver_args = launch_info.GetArguments();
- debugserver_args.Clear();
- char arg_cstr[PATH_MAX];
+ Args &debugserver_args = launch_info.GetArguments();
+ debugserver_args.Clear();
+ char arg_cstr[PATH_MAX];
- // Start args with "debugserver /file/path -r --"
- debugserver_args.AppendArgument(debugserver_path);
+ // Start args with "debugserver /file/path -r --"
+ debugserver_args.AppendArgument(llvm::StringRef(debugserver_path));
#if !defined(__APPLE__)
- // First argument to lldb-server must be mode in which to run.
- debugserver_args.AppendArgument("gdbserver");
+ // First argument to lldb-server must be mode in which to run.
+ debugserver_args.AppendArgument(llvm::StringRef("gdbserver"));
#endif
- // If a url is supplied then use it
- if (url)
- debugserver_args.AppendArgument(url);
+ // If a url is supplied then use it
+ if (url)
+ debugserver_args.AppendArgument(llvm::StringRef(url));
+
+ if (pass_comm_fd >= 0) {
+ StreamString fd_arg;
+ fd_arg.Printf("--fd=%i", pass_comm_fd);
+ debugserver_args.AppendArgument(fd_arg.GetString());
+ // Send "pass_comm_fd" down to the inferior so it can use it to
+ // communicate back with this process
+ launch_info.AppendDuplicateFileAction(pass_comm_fd, pass_comm_fd);
+ }
- // use native registers, not the GDB registers
- debugserver_args.AppendArgument("--native-regs");
+ // use native registers, not the GDB registers
+ debugserver_args.AppendArgument(llvm::StringRef("--native-regs"));
- if (launch_info.GetLaunchInSeparateProcessGroup())
- {
- debugserver_args.AppendArgument("--setsid");
- }
+ if (launch_info.GetLaunchInSeparateProcessGroup()) {
+ debugserver_args.AppendArgument(llvm::StringRef("--setsid"));
+ }
- llvm::SmallString<PATH_MAX> named_pipe_path;
- // socket_pipe is used by debug server to communicate back either
- // TCP port or domain socket name which it listens on.
- // The second purpose of the pipe to serve as a synchronization point -
- // once data is written to the pipe, debug server is up and running.
- Pipe socket_pipe;
-
- // port is null when debug server should listen on domain socket -
- // we're not interested in port value but rather waiting for debug server
- // to become available.
- if ((port != nullptr && *port == 0) || port == nullptr)
- {
- if (url)
- {
- // Create a temporary file to get the stdout/stderr and redirect the
- // output of the command into this file. We will later read this file
- // if all goes well and fill the data into "command_output_ptr"
-
-#if defined(__APPLE__)
- // Binding to port zero, we need to figure out what port it ends up
- // using using a named pipe...
- error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe", false, named_pipe_path);
- if (error.Fail())
- {
- if (log)
- log->Printf("GDBRemoteCommunication::%s() "
- "named pipe creation failed: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
- debugserver_args.AppendArgument("--named-pipe");
- debugserver_args.AppendArgument(named_pipe_path.c_str());
-#else
- // Binding to port zero, we need to figure out what port it ends up
- // using using an unnamed pipe...
- error = socket_pipe.CreateNew(true);
- if (error.Fail())
- {
- if (log)
- log->Printf("GDBRemoteCommunication::%s() "
- "unnamed pipe creation failed: %s",
- __FUNCTION__, error.AsCString());
- return error;
- }
- int write_fd = socket_pipe.GetWriteFileDescriptor();
- debugserver_args.AppendArgument("--pipe");
- debugserver_args.AppendArgument(std::to_string(write_fd).c_str());
- launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor());
-#endif
- }
- else
- {
- // No host and port given, so lets listen on our end and make the debugserver
- // connect to us..
- error = StartListenThread ("127.0.0.1", 0);
- if (error.Fail())
- {
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() unable to start listen thread: %s", __FUNCTION__, error.AsCString());
- return error;
- }
-
- ConnectionFileDescriptor *connection = (ConnectionFileDescriptor *)GetConnection ();
- // Wait for 10 seconds to resolve the bound port
- *port = connection->GetListeningPort(10);
- if (*port > 0)
- {
- char port_cstr[32];
- snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", *port);
- // Send the host and port down that debugserver and specify an option
- // so that it connects back to the port we are listening to in this process
- debugserver_args.AppendArgument("--reverse-connect");
- debugserver_args.AppendArgument(port_cstr);
- }
- else
- {
- error.SetErrorString ("failed to bind to port 0 on 127.0.0.1");
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString());
- return error;
- }
- }
- }
-
- const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
- if (env_debugserver_log_file)
- {
- ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-file=%s", env_debugserver_log_file);
- debugserver_args.AppendArgument(arg_cstr);
- }
-
+ llvm::SmallString<PATH_MAX> named_pipe_path;
+ // socket_pipe is used by debug server to communicate back either
+ // TCP port or domain socket name which it listens on.
+ // The second purpose of the pipe to serve as a synchronization point -
+ // once data is written to the pipe, debug server is up and running.
+ Pipe socket_pipe;
+
+ // port is null when debug server should listen on domain socket -
+ // we're not interested in port value but rather waiting for debug server
+ // to become available.
+ if (pass_comm_fd == -1 &&
+ ((port != nullptr && *port == 0) || port == nullptr)) {
+ if (url) {
+// Create a temporary file to get the stdout/stderr and redirect the
+// output of the command into this file. We will later read this file
+// if all goes well and fill the data into "command_output_ptr"
#if defined(__APPLE__)
- const char *env_debugserver_log_flags = getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
- if (env_debugserver_log_flags)
- {
- ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-flags=%s", env_debugserver_log_flags);
- debugserver_args.AppendArgument(arg_cstr);
+ // Binding to port zero, we need to figure out what port it ends up
+ // using using a named pipe...
+ error = socket_pipe.CreateWithUniqueName("debugserver-named-pipe",
+ false, named_pipe_path);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() "
+ "named pipe creation failed: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
}
+ debugserver_args.AppendArgument(llvm::StringRef("--named-pipe"));
+ debugserver_args.AppendArgument(named_pipe_path);
#else
- const char *env_debugserver_log_channels = getenv("LLDB_SERVER_LOG_CHANNELS");
- if (env_debugserver_log_channels)
- {
- ::snprintf (arg_cstr, sizeof(arg_cstr), "--log-channels=%s", env_debugserver_log_channels);
- debugserver_args.AppendArgument(arg_cstr);
+ // Binding to port zero, we need to figure out what port it ends up
+ // using using an unnamed pipe...
+ error = socket_pipe.CreateNew(true);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() "
+ "unnamed pipe creation failed: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
}
+ int write_fd = socket_pipe.GetWriteFileDescriptor();
+ debugserver_args.AppendArgument(llvm::StringRef("--pipe"));
+ debugserver_args.AppendArgument(llvm::to_string(write_fd));
+ launch_info.AppendCloseFileAction(socket_pipe.GetReadFileDescriptor());
#endif
-
- // Add additional args, starting with LLDB_DEBUGSERVER_EXTRA_ARG_1 until an env var doesn't come back.
- uint32_t env_var_index = 1;
- bool has_env_var;
- do
- {
- char env_var_name[64];
- snprintf (env_var_name, sizeof (env_var_name), "LLDB_DEBUGSERVER_EXTRA_ARG_%" PRIu32, env_var_index++);
- const char *extra_arg = getenv(env_var_name);
- has_env_var = extra_arg != nullptr;
-
- if (has_env_var)
- {
- debugserver_args.AppendArgument (extra_arg);
- if (log)
- log->Printf ("GDBRemoteCommunication::%s adding env var %s contents to stub command line (%s)", __FUNCTION__, env_var_name, extra_arg);
- }
- } while (has_env_var);
-
- if (inferior_args.GetArgumentCount() > 0)
- {
- debugserver_args.AppendArgument ("--");
- debugserver_args.AppendArguments (inferior_args);
+ } else {
+ // No host and port given, so lets listen on our end and make the
+ // debugserver
+ // connect to us..
+ error = StartListenThread("127.0.0.1", 0);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() unable to start listen "
+ "thread: %s",
+ __FUNCTION__, error.AsCString());
+ return error;
}
- // Copy the current environment to the gdbserver/debugserver instance
- StringList env;
- if (Host::GetEnvironment(env))
- {
- for (size_t i = 0; i < env.GetSize(); ++i)
- launch_info.GetEnvironmentEntries().AppendArgument(env[i].c_str());
+ ConnectionFileDescriptor *connection =
+ (ConnectionFileDescriptor *)GetConnection();
+ // Wait for 10 seconds to resolve the bound port
+ uint16_t port_ = connection->GetListeningPort(10);
+ if (port_ > 0) {
+ char port_cstr[32];
+ snprintf(port_cstr, sizeof(port_cstr), "127.0.0.1:%i", port_);
+ // Send the host and port down that debugserver and specify an option
+ // so that it connects back to the port we are listening to in this
+ // process
+ debugserver_args.AppendArgument(llvm::StringRef("--reverse-connect"));
+ debugserver_args.AppendArgument(llvm::StringRef(port_cstr));
+ if (port)
+ *port = port_;
+ } else {
+ error.SetErrorString("failed to bind to port 0 on 127.0.0.1");
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__,
+ error.AsCString());
+ return error;
}
+ }
+ }
- // Close STDIN, STDOUT and STDERR.
- launch_info.AppendCloseFileAction (STDIN_FILENO);
- launch_info.AppendCloseFileAction (STDOUT_FILENO);
- launch_info.AppendCloseFileAction (STDERR_FILENO);
+ const char *env_debugserver_log_file = getenv("LLDB_DEBUGSERVER_LOG_FILE");
+ if (env_debugserver_log_file) {
+ ::snprintf(arg_cstr, sizeof(arg_cstr), "--log-file=%s",
+ env_debugserver_log_file);
+ debugserver_args.AppendArgument(llvm::StringRef(arg_cstr));
+ }
- // Redirect STDIN, STDOUT and STDERR to "/dev/null".
- launch_info.AppendSuppressFileAction (STDIN_FILENO, true, false);
- launch_info.AppendSuppressFileAction (STDOUT_FILENO, false, true);
- launch_info.AppendSuppressFileAction (STDERR_FILENO, false, true);
+#if defined(__APPLE__)
+ const char *env_debugserver_log_flags =
+ getenv("LLDB_DEBUGSERVER_LOG_FLAGS");
+ if (env_debugserver_log_flags) {
+ ::snprintf(arg_cstr, sizeof(arg_cstr), "--log-flags=%s",
+ env_debugserver_log_flags);
+ debugserver_args.AppendArgument(llvm::StringRef(arg_cstr));
+ }
+#else
+ const char *env_debugserver_log_channels =
+ getenv("LLDB_SERVER_LOG_CHANNELS");
+ if (env_debugserver_log_channels) {
+ ::snprintf(arg_cstr, sizeof(arg_cstr), "--log-channels=%s",
+ env_debugserver_log_channels);
+ debugserver_args.AppendArgument(llvm::StringRef(arg_cstr));
+ }
+#endif
+ // Add additional args, starting with LLDB_DEBUGSERVER_EXTRA_ARG_1 until an
+ // env var doesn't come back.
+ uint32_t env_var_index = 1;
+ bool has_env_var;
+ do {
+ char env_var_name[64];
+ snprintf(env_var_name, sizeof(env_var_name),
+ "LLDB_DEBUGSERVER_EXTRA_ARG_%" PRIu32, env_var_index++);
+ const char *extra_arg = getenv(env_var_name);
+ has_env_var = extra_arg != nullptr;
+
+ if (has_env_var) {
+ debugserver_args.AppendArgument(llvm::StringRef(extra_arg));
if (log)
- {
- StreamString string_stream;
- Platform *const platform = nullptr;
- launch_info.Dump(string_stream, platform);
- log->Printf("launch info for gdb-remote stub:\n%s", string_stream.GetString().c_str());
- }
- error = Host::LaunchProcess(launch_info);
-
- if (error.Success() &&
- launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
- {
- if (named_pipe_path.size() > 0)
- {
- error = socket_pipe.OpenAsReader(named_pipe_path, false);
- if (error.Fail())
- if (log)
- log->Printf("GDBRemoteCommunication::%s() "
- "failed to open named pipe %s for reading: %s",
- __FUNCTION__, named_pipe_path.c_str(), error.AsCString());
- }
-
- if (socket_pipe.CanWrite())
- socket_pipe.CloseWriteFileDescriptor();
- if (socket_pipe.CanRead())
- {
- char port_cstr[PATH_MAX] = {0};
- port_cstr[0] = '\0';
- size_t num_bytes = sizeof(port_cstr);
- // Read port from pipe with 10 second timeout.
- error = socket_pipe.ReadWithTimeout(port_cstr, num_bytes,
- std::chrono::seconds{10}, num_bytes);
- if (error.Success() && (port != nullptr))
- {
- assert(num_bytes > 0 && port_cstr[num_bytes-1] == '\0');
- *port = StringConvert::ToUInt32(port_cstr, 0);
- if (log)
- log->Printf("GDBRemoteCommunication::%s() "
- "debugserver listens %u port",
- __FUNCTION__, *port);
- }
- else
- {
- if (log)
- log->Printf("GDBRemoteCommunication::%s() "
- "failed to read a port value from pipe %s: %s",
- __FUNCTION__, named_pipe_path.c_str(), error.AsCString());
-
- }
- socket_pipe.Close();
- }
-
- if (named_pipe_path.size() > 0)
- {
- const auto err = socket_pipe.Delete(named_pipe_path);
- if (err.Fail())
- {
- if (log)
- log->Printf ("GDBRemoteCommunication::%s failed to delete pipe %s: %s",
- __FUNCTION__, named_pipe_path.c_str(), err.AsCString());
- }
- }
+ log->Printf("GDBRemoteCommunication::%s adding env var %s contents "
+ "to stub command line (%s)",
+ __FUNCTION__, env_var_name, extra_arg);
+ }
+ } while (has_env_var);
+
+ if (inferior_args && inferior_args->GetArgumentCount() > 0) {
+ debugserver_args.AppendArgument(llvm::StringRef("--"));
+ debugserver_args.AppendArguments(*inferior_args);
+ }
- // Make sure we actually connect with the debugserver...
- JoinListenThread();
- }
+ // Copy the current environment to the gdbserver/debugserver instance
+ StringList env;
+ if (Host::GetEnvironment(env)) {
+ for (size_t i = 0; i < env.GetSize(); ++i)
+ launch_info.GetEnvironmentEntries().AppendArgument(env[i]);
}
- else
- {
- error.SetErrorStringWithFormat ("unable to locate " DEBUGSERVER_BASENAME );
+
+ // Close STDIN, STDOUT and STDERR.
+ launch_info.AppendCloseFileAction(STDIN_FILENO);
+ launch_info.AppendCloseFileAction(STDOUT_FILENO);
+ launch_info.AppendCloseFileAction(STDERR_FILENO);
+
+ // Redirect STDIN, STDOUT and STDERR to "/dev/null".
+ launch_info.AppendSuppressFileAction(STDIN_FILENO, true, false);
+ launch_info.AppendSuppressFileAction(STDOUT_FILENO, false, true);
+ launch_info.AppendSuppressFileAction(STDERR_FILENO, false, true);
+
+ if (log) {
+ StreamString string_stream;
+ Platform *const platform = nullptr;
+ launch_info.Dump(string_stream, platform);
+ log->Printf("launch info for gdb-remote stub:\n%s",
+ string_stream.GetData());
}
+ error = Host::LaunchProcess(launch_info);
+
+ if (error.Success() &&
+ (launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) &&
+ pass_comm_fd == -1) {
+ if (named_pipe_path.size() > 0) {
+ error = socket_pipe.OpenAsReader(named_pipe_path, false);
+ if (error.Fail())
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() "
+ "failed to open named pipe %s for reading: %s",
+ __FUNCTION__, named_pipe_path.c_str(),
+ error.AsCString());
+ }
+
+ if (socket_pipe.CanWrite())
+ socket_pipe.CloseWriteFileDescriptor();
+ if (socket_pipe.CanRead()) {
+ char port_cstr[PATH_MAX] = {0};
+ port_cstr[0] = '\0';
+ size_t num_bytes = sizeof(port_cstr);
+ // Read port from pipe with 10 second timeout.
+ error = socket_pipe.ReadWithTimeout(
+ port_cstr, num_bytes, std::chrono::seconds{10}, num_bytes);
+ if (error.Success() && (port != nullptr)) {
+ assert(num_bytes > 0 && port_cstr[num_bytes - 1] == '\0');
+ *port = StringConvert::ToUInt32(port_cstr, 0);
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() "
+ "debugserver listens %u port",
+ __FUNCTION__, *port);
+ } else {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() "
+ "failed to read a port value from pipe %s: %s",
+ __FUNCTION__, named_pipe_path.c_str(),
+ error.AsCString());
+ }
+ socket_pipe.Close();
+ }
+
+ if (named_pipe_path.size() > 0) {
+ const auto err = socket_pipe.Delete(named_pipe_path);
+ if (err.Fail()) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunication::%s failed to delete pipe %s: %s",
+ __FUNCTION__, named_pipe_path.c_str(), err.AsCString());
+ }
+ }
- if (error.Fail())
- {
- if (log)
- log->Printf ("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__, error.AsCString());
+ // Make sure we actually connect with the debugserver...
+ JoinListenThread();
}
+ } else {
+ error.SetErrorStringWithFormat("unable to locate " DEBUGSERVER_BASENAME);
+ }
- return error;
-}
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunication::%s() failed: %s", __FUNCTION__,
+ error.AsCString());
+ }
-void
-GDBRemoteCommunication::DumpHistory(Stream &strm)
-{
- m_history.Dump (strm);
+ return error;
}
-GDBRemoteCommunication::ScopedTimeout::ScopedTimeout (GDBRemoteCommunication& gdb_comm,
- uint32_t timeout) :
- m_gdb_comm (gdb_comm)
-{
- m_saved_timeout = m_gdb_comm.SetPacketTimeout (timeout);
+void GDBRemoteCommunication::DumpHistory(Stream &strm) { m_history.Dump(strm); }
+
+GDBRemoteCommunication::ScopedTimeout::ScopedTimeout(
+ GDBRemoteCommunication &gdb_comm, std::chrono::seconds timeout)
+ : m_gdb_comm(gdb_comm) {
+ m_saved_timeout = m_gdb_comm.SetPacketTimeout(timeout);
}
-GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout ()
-{
- m_gdb_comm.SetPacketTimeout (m_saved_timeout);
+GDBRemoteCommunication::ScopedTimeout::~ScopedTimeout() {
+ m_gdb_comm.SetPacketTimeout(m_saved_timeout);
}
-// This function is called via the Communications class read thread when bytes become available
-// for this connection. This function will consume all incoming bytes and try to parse whole
-// packets as they become available. Full packets are placed in a queue, so that all packet
-// requests can simply pop from this queue. Async notification packets will be dispatched
+// This function is called via the Communications class read thread when bytes
+// become available
+// for this connection. This function will consume all incoming bytes and try to
+// parse whole
+// packets as they become available. Full packets are placed in a queue, so that
+// all packet
+// requests can simply pop from this queue. Async notification packets will be
+// dispatched
// immediately to the ProcessGDBRemote Async thread via an event.
-void GDBRemoteCommunication::AppendBytesToCache (const uint8_t * bytes, size_t len, bool broadcast, lldb::ConnectionStatus status)
-{
- StringExtractorGDBRemote packet;
-
- while (true)
- {
- PacketType type = CheckForPacket(bytes, len, packet);
-
- // scrub the data so we do not pass it back to CheckForPacket
- // on future passes of the loop
- bytes = nullptr;
- len = 0;
-
- // we may have received no packet so lets bail out
- if (type == PacketType::Invalid)
- break;
-
- if (type == PacketType::Standard)
- {
- // scope for the mutex
- {
- // lock down the packet queue
- Mutex::Locker locker(m_packet_queue_mutex);
- // push a new packet into the queue
- m_packet_queue.push(packet);
- // Signal condition variable that we have a packet
- m_condition_queue_not_empty.Signal();
-
- }
- }
+void GDBRemoteCommunication::AppendBytesToCache(const uint8_t *bytes,
+ size_t len, bool broadcast,
+ lldb::ConnectionStatus status) {
+ StringExtractorGDBRemote packet;
+
+ while (true) {
+ PacketType type = CheckForPacket(bytes, len, packet);
+
+ // scrub the data so we do not pass it back to CheckForPacket
+ // on future passes of the loop
+ bytes = nullptr;
+ len = 0;
+
+ // we may have received no packet so lets bail out
+ if (type == PacketType::Invalid)
+ break;
+
+ if (type == PacketType::Standard) {
+ // scope for the mutex
+ {
+ // lock down the packet queue
+ std::lock_guard<std::mutex> guard(m_packet_queue_mutex);
+ // push a new packet into the queue
+ m_packet_queue.push(packet);
+ // Signal condition variable that we have a packet
+ m_condition_queue_not_empty.notify_one();
+ }
+ }
- if (type == PacketType::Notify)
- {
- // put this packet into an event
- const char *pdata = packet.GetStringRef().c_str();
+ if (type == PacketType::Notify) {
+ // put this packet into an event
+ const char *pdata = packet.GetStringRef().c_str();
- // as the communication class, we are a broadcaster and the
- // async thread is tuned to listen to us
- BroadcastEvent(
- eBroadcastBitGdbReadThreadGotNotify,
- new EventDataBytes(pdata));
- }
+ // as the communication class, we are a broadcaster and the
+ // async thread is tuned to listen to us
+ BroadcastEvent(eBroadcastBitGdbReadThreadGotNotify,
+ new EventDataBytes(pdata));
}
+ }
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
index 2a01bce..1f3fa17 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h
@@ -12,365 +12,275 @@
// C Includes
// C++ Includes
-#include <string>
+#include <condition_variable>
+#include <mutex>
#include <queue>
+#include <string>
#include <vector>
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-public.h"
#include "lldb/Core/Communication.h"
#include "lldb/Core/Listener.h"
#include "lldb/Host/HostThread.h"
-#include "lldb/Host/Mutex.h"
#include "lldb/Host/Predicate.h"
-#include "lldb/Host/TimeValue.h"
#include "lldb/Interpreter/Args.h"
+#include "lldb/lldb-public.h"
#include "Utility/StringExtractorGDBRemote.h"
namespace lldb_private {
namespace process_gdb_remote {
-typedef enum
-{
- eStoppointInvalid = -1,
- eBreakpointSoftware = 0,
- eBreakpointHardware,
- eWatchpointWrite,
- eWatchpointRead,
- eWatchpointReadWrite
+typedef enum {
+ eStoppointInvalid = -1,
+ eBreakpointSoftware = 0,
+ eBreakpointHardware,
+ eWatchpointWrite,
+ eWatchpointRead,
+ eWatchpointReadWrite
} GDBStoppointType;
-enum class CompressionType
-{
- None = 0, // no compression
- ZlibDeflate, // zlib's deflate compression scheme, requires zlib or Apple's libcompression
- LZFSE, // an Apple compression scheme, requires Apple's libcompression
- LZ4, // lz compression - called "lz4 raw" in libcompression terms, compat with https://code.google.com/p/lz4/
- LZMA, // Lempel–Ziv–Markov chain algorithm
+enum class CompressionType {
+ None = 0, // no compression
+ ZlibDeflate, // zlib's deflate compression scheme, requires zlib or Apple's
+ // libcompression
+ LZFSE, // an Apple compression scheme, requires Apple's libcompression
+ LZ4, // lz compression - called "lz4 raw" in libcompression terms, compat with
+ // https://code.google.com/p/lz4/
+ LZMA, // Lempel–Ziv–Markov chain algorithm
};
class ProcessGDBRemote;
-class GDBRemoteCommunication : public Communication
-{
+class GDBRemoteCommunication : public Communication {
public:
- enum
- {
- eBroadcastBitRunPacketSent = kLoUserBroadcastBit,
- eBroadcastBitGdbReadThreadGotNotify = kLoUserBroadcastBit << 1 // Sent when we received a notify packet.
- };
+ enum {
+ eBroadcastBitRunPacketSent = kLoUserBroadcastBit,
+ eBroadcastBitGdbReadThreadGotNotify =
+ kLoUserBroadcastBit << 1 // Sent when we received a notify packet.
+ };
+
+ enum class PacketType { Invalid = 0, Standard, Notify };
+
+ enum class PacketResult {
+ Success = 0, // Success
+ ErrorSendFailed, // Error sending the packet
+ ErrorSendAck, // Didn't get an ack back after sending a packet
+ ErrorReplyFailed, // Error getting the reply
+ ErrorReplyTimeout, // Timed out waiting for reply
+ ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that
+ // was sent
+ ErrorReplyAck, // Sending reply ack failed
+ ErrorDisconnected, // We were disconnected
+ ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet
+ // request
+ };
+
+ // Class to change the timeout for a given scope and restore it to the
+ // original value when the
+ // created ScopedTimeout object got out of scope
+ class ScopedTimeout {
+ public:
+ ScopedTimeout(GDBRemoteCommunication &gdb_comm,
+ std::chrono::seconds timeout);
+ ~ScopedTimeout();
+
+ private:
+ GDBRemoteCommunication &m_gdb_comm;
+ std::chrono::seconds m_saved_timeout;
+ };
+
+ GDBRemoteCommunication(const char *comm_name, const char *listener_name);
+
+ ~GDBRemoteCommunication() override;
+
+ PacketResult GetAck();
+
+ size_t SendAck();
+
+ size_t SendNack();
+
+ char CalculcateChecksum(llvm::StringRef payload);
+
+ PacketType CheckForPacket(const uint8_t *src, size_t src_len,
+ StringExtractorGDBRemote &packet);
+
+ bool GetSendAcks() { return m_send_acks; }
+
+ //------------------------------------------------------------------
+ // Set the global packet timeout.
+ //
+ // For clients, this is the timeout that gets used when sending
+ // packets and waiting for responses. For servers, this is used when waiting
+ // for ACKs.
+ //------------------------------------------------------------------
+ std::chrono::seconds SetPacketTimeout(std::chrono::seconds packet_timeout) {
+ const auto old_packet_timeout = m_packet_timeout;
+ m_packet_timeout = packet_timeout;
+ return old_packet_timeout;
+ }
+
+ std::chrono::seconds GetPacketTimeout() const { return m_packet_timeout; }
+
+ //------------------------------------------------------------------
+ // Start a debugserver instance on the current host using the
+ // supplied connection URL.
+ //------------------------------------------------------------------
+ Error StartDebugserverProcess(
+ const char *url,
+ Platform *platform, // If non nullptr, then check with the platform for
+ // the GDB server binary if it can't be located
+ ProcessLaunchInfo &launch_info, uint16_t *port, const Args *inferior_args,
+ int pass_comm_fd); // Communication file descriptor to pass during
+ // fork/exec to avoid having to connect/accept
+
+ void DumpHistory(Stream &strm);
- enum class PacketType
- {
- Invalid = 0,
- Standard,
- Notify
- };
-
- enum class PacketResult
- {
- Success = 0, // Success
- ErrorSendFailed, // Error sending the packet
- ErrorSendAck, // Didn't get an ack back after sending a packet
- ErrorReplyFailed, // Error getting the reply
- ErrorReplyTimeout, // Timed out waiting for reply
- ErrorReplyInvalid, // Got a reply but it wasn't valid for the packet that was sent
- ErrorReplyAck, // Sending reply ack failed
- ErrorDisconnected, // We were disconnected
- ErrorNoSequenceLock // We couldn't get the sequence lock for a multi-packet request
+protected:
+ class History {
+ public:
+ enum PacketType {
+ ePacketTypeInvalid = 0,
+ ePacketTypeSend,
+ ePacketTypeRecv
};
- // Class to change the timeout for a given scope and restore it to the original value when the
- // created ScopedTimeout object got out of scope
- class ScopedTimeout
- {
- public:
- ScopedTimeout (GDBRemoteCommunication& gdb_comm, uint32_t timeout);
- ~ScopedTimeout ();
-
- private:
- GDBRemoteCommunication& m_gdb_comm;
- uint32_t m_saved_timeout;
+ struct Entry {
+ Entry()
+ : packet(), type(ePacketTypeInvalid), bytes_transmitted(0),
+ packet_idx(0), tid(LLDB_INVALID_THREAD_ID) {}
+
+ void Clear() {
+ packet.clear();
+ type = ePacketTypeInvalid;
+ bytes_transmitted = 0;
+ packet_idx = 0;
+ tid = LLDB_INVALID_THREAD_ID;
+ }
+ std::string packet;
+ PacketType type;
+ uint32_t bytes_transmitted;
+ uint32_t packet_idx;
+ lldb::tid_t tid;
};
- GDBRemoteCommunication(const char *comm_name,
- const char *listener_name);
-
- ~GDBRemoteCommunication() override;
-
- PacketResult
- GetAck ();
-
- size_t
- SendAck ();
+ History(uint32_t size);
- size_t
- SendNack ();
+ ~History();
- char
- CalculcateChecksum (const char *payload,
- size_t payload_length);
+ // For single char packets for ack, nack and /x03
+ void AddPacket(char packet_char, PacketType type,
+ uint32_t bytes_transmitted);
- bool
- GetSequenceMutex(Mutex::Locker& locker, const char *failure_message = nullptr);
+ void AddPacket(const std::string &src, uint32_t src_len, PacketType type,
+ uint32_t bytes_transmitted);
- PacketType
- CheckForPacket (const uint8_t *src,
- size_t src_len,
- StringExtractorGDBRemote &packet);
+ void Dump(Stream &strm) const;
- bool
- IsRunning() const
- {
- return m_public_is_running.GetValue();
- }
+ void Dump(Log *log) const;
- bool
- GetSendAcks ()
- {
- return m_send_acks;
- }
+ bool DidDumpToLog() const { return m_dumped_to_log; }
- //------------------------------------------------------------------
- // Client and server must implement these pure virtual functions
- //------------------------------------------------------------------
- virtual bool
- GetThreadSuffixSupported () = 0;
-
- //------------------------------------------------------------------
- // Set the global packet timeout.
- //
- // For clients, this is the timeout that gets used when sending
- // packets and waiting for responses. For servers, this might not
- // get used, and if it doesn't this should be moved to the
- // GDBRemoteCommunicationClient.
- //------------------------------------------------------------------
- uint32_t
- SetPacketTimeout (uint32_t packet_timeout)
- {
- const uint32_t old_packet_timeout = m_packet_timeout;
- m_packet_timeout = packet_timeout;
- return old_packet_timeout;
+ protected:
+ uint32_t GetFirstSavedPacketIndex() const {
+ if (m_total_packet_count < m_packets.size())
+ return 0;
+ else
+ return m_curr_idx + 1;
}
- uint32_t
- GetPacketTimeoutInMicroSeconds () const
- {
- return m_packet_timeout * TimeValue::MicroSecPerSec;
+ uint32_t GetNumPacketsInHistory() const {
+ if (m_total_packet_count < m_packets.size())
+ return m_total_packet_count;
+ else
+ return (uint32_t)m_packets.size();
}
- //------------------------------------------------------------------
- // Start a debugserver instance on the current host using the
- // supplied connection URL.
- //------------------------------------------------------------------
- Error
- StartDebugserverProcess(const char *url,
- Platform *platform, // If non nullptr, then check with the platform for the GDB server binary if it can't be located
- ProcessLaunchInfo &launch_info,
- uint16_t *port,
- const Args& inferior_args = Args());
-
- void
- DumpHistory(Stream &strm);
-
-protected:
- class History
- {
- public:
- enum PacketType
- {
- ePacketTypeInvalid = 0,
- ePacketTypeSend,
- ePacketTypeRecv
- };
-
- struct Entry
- {
- Entry() :
- packet(),
- type (ePacketTypeInvalid),
- bytes_transmitted (0),
- packet_idx (0),
- tid (LLDB_INVALID_THREAD_ID)
- {
- }
-
- void
- Clear ()
- {
- packet.clear();
- type = ePacketTypeInvalid;
- bytes_transmitted = 0;
- packet_idx = 0;
- tid = LLDB_INVALID_THREAD_ID;
- }
- std::string packet;
- PacketType type;
- uint32_t bytes_transmitted;
- uint32_t packet_idx;
- lldb::tid_t tid;
- };
-
- History (uint32_t size);
-
- ~History ();
-
- // For single char packets for ack, nack and /x03
- void
- AddPacket (char packet_char,
- PacketType type,
- uint32_t bytes_transmitted);
-
- void
- AddPacket (const std::string &src,
- uint32_t src_len,
- PacketType type,
- uint32_t bytes_transmitted);
-
- void
- Dump (Stream &strm) const;
-
- void
- Dump (Log *log) const;
-
- bool
- DidDumpToLog () const
- {
- return m_dumped_to_log;
- }
-
- protected:
- uint32_t
- GetFirstSavedPacketIndex () const
- {
- if (m_total_packet_count < m_packets.size())
- return 0;
- else
- return m_curr_idx + 1;
- }
-
- uint32_t
- GetNumPacketsInHistory () const
- {
- if (m_total_packet_count < m_packets.size())
- return m_total_packet_count;
- else
- return (uint32_t)m_packets.size();
- }
-
- uint32_t
- GetNextIndex()
- {
- ++m_total_packet_count;
- const uint32_t idx = m_curr_idx;
- m_curr_idx = NormalizeIndex(idx + 1);
- return idx;
- }
-
- uint32_t
- NormalizeIndex (uint32_t i) const
- {
- return i % m_packets.size();
- }
-
- std::vector<Entry> m_packets;
- uint32_t m_curr_idx;
- uint32_t m_total_packet_count;
- mutable bool m_dumped_to_log;
- };
-
- uint32_t m_packet_timeout;
- uint32_t m_echo_number;
- LazyBool m_supports_qEcho;
-#ifdef ENABLE_MUTEX_ERROR_CHECKING
- TrackingMutex m_sequence_mutex;
-#else
- Mutex m_sequence_mutex; // Restrict access to sending/receiving packets to a single thread at a time
-#endif
- Predicate<bool> m_public_is_running;
- Predicate<bool> m_private_is_running;
- History m_history;
- bool m_send_acks;
- bool m_is_platform; // Set to true if this class represents a platform,
- // false if this class represents a debug session for
- // a single process
-
- CompressionType m_compression_type;
-
- PacketResult
- SendPacket (const char *payload,
- size_t payload_length);
-
- PacketResult
- SendPacketNoLock (const char *payload,
- size_t payload_length);
-
- PacketResult
- ReadPacket (StringExtractorGDBRemote &response, uint32_t timeout_usec, bool sync_on_timeout);
-
- // Pop a packet from the queue in a thread safe manner
- PacketResult
- PopPacketFromQueue (StringExtractorGDBRemote &response, uint32_t timeout_usec);
-
- PacketResult
- WaitForPacketWithTimeoutMicroSecondsNoLock (StringExtractorGDBRemote &response,
- uint32_t timeout_usec,
- bool sync_on_timeout);
-
- bool
- WaitForNotRunningPrivate (const TimeValue *timeout_ptr);
-
- bool
- CompressionIsEnabled ()
- {
- return m_compression_type != CompressionType::None;
+ uint32_t GetNextIndex() {
+ ++m_total_packet_count;
+ const uint32_t idx = m_curr_idx;
+ m_curr_idx = NormalizeIndex(idx + 1);
+ return idx;
}
- // If compression is enabled, decompress the packet in m_bytes and update
- // m_bytes with the uncompressed version.
- // Returns 'true' packet was decompressed and m_bytes is the now-decompressed text.
- // Returns 'false' if unable to decompress or if the checksum was invalid.
- //
- // NB: Once the packet has been decompressed, checksum cannot be computed based
- // on m_bytes. The checksum was for the compressed packet.
- bool
- DecompressPacket ();
-
- Error
- StartListenThread (const char *hostname = "127.0.0.1", uint16_t port = 0);
-
- bool
- JoinListenThread ();
-
- static lldb::thread_result_t
- ListenThread (lldb::thread_arg_t arg);
-
- // GDB-Remote read thread
- // . this thread constantly tries to read from the communication
- // class and stores all packets received in a queue. The usual
- // threads read requests simply pop packets off the queue in the
- // usual order.
- // This setup allows us to intercept and handle async packets, such
- // as the notify packet.
-
- // This method is defined as part of communication.h
- // when the read thread gets any bytes it will pass them on to this function
- void AppendBytesToCache(const uint8_t * bytes,
- size_t len,
- bool broadcast,
- lldb::ConnectionStatus status) override;
+ uint32_t NormalizeIndex(uint32_t i) const { return i % m_packets.size(); }
+
+ std::vector<Entry> m_packets;
+ uint32_t m_curr_idx;
+ uint32_t m_total_packet_count;
+ mutable bool m_dumped_to_log;
+ };
+
+ std::chrono::seconds m_packet_timeout;
+ uint32_t m_echo_number;
+ LazyBool m_supports_qEcho;
+ History m_history;
+ bool m_send_acks;
+ bool m_is_platform; // Set to true if this class represents a platform,
+ // false if this class represents a debug session for
+ // a single process
+
+ CompressionType m_compression_type;
+
+ PacketResult SendPacketNoLock(llvm::StringRef payload);
+
+ PacketResult ReadPacket(StringExtractorGDBRemote &response,
+ Timeout<std::micro> timeout, bool sync_on_timeout);
+
+ // Pop a packet from the queue in a thread safe manner
+ PacketResult PopPacketFromQueue(StringExtractorGDBRemote &response,
+ Timeout<std::micro> timeout);
+
+ PacketResult WaitForPacketNoLock(StringExtractorGDBRemote &response,
+ Timeout<std::micro> timeout,
+ bool sync_on_timeout);
+
+ bool CompressionIsEnabled() {
+ return m_compression_type != CompressionType::None;
+ }
+
+ // If compression is enabled, decompress the packet in m_bytes and update
+ // m_bytes with the uncompressed version.
+ // Returns 'true' packet was decompressed and m_bytes is the now-decompressed
+ // text.
+ // Returns 'false' if unable to decompress or if the checksum was invalid.
+ //
+ // NB: Once the packet has been decompressed, checksum cannot be computed
+ // based
+ // on m_bytes. The checksum was for the compressed packet.
+ bool DecompressPacket();
+
+ Error StartListenThread(const char *hostname = "127.0.0.1",
+ uint16_t port = 0);
+
+ bool JoinListenThread();
+
+ static lldb::thread_result_t ListenThread(lldb::thread_arg_t arg);
+
+ // GDB-Remote read thread
+ // . this thread constantly tries to read from the communication
+ // class and stores all packets received in a queue. The usual
+ // threads read requests simply pop packets off the queue in the
+ // usual order.
+ // This setup allows us to intercept and handle async packets, such
+ // as the notify packet.
+
+ // This method is defined as part of communication.h
+ // when the read thread gets any bytes it will pass them on to this function
+ void AppendBytesToCache(const uint8_t *bytes, size_t len, bool broadcast,
+ lldb::ConnectionStatus status) override;
private:
- std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue
- lldb_private::Mutex m_packet_queue_mutex; // Mutex for accessing queue
- Condition m_condition_queue_not_empty; // Condition variable to wait for packets
+ std::queue<StringExtractorGDBRemote> m_packet_queue; // The packet queue
+ std::mutex m_packet_queue_mutex; // Mutex for accessing queue
+ std::condition_variable
+ m_condition_queue_not_empty; // Condition variable to wait for packets
- HostThread m_listen_thread;
- std::string m_listen_url;
+ HostThread m_listen_thread;
+ std::string m_listen_url;
- DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunication);
+ DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunication);
};
} // namespace process_gdb_remote
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index a792bbb..b70f090 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
#include "GDBRemoteCommunicationClient.h"
// C Includes
@@ -15,48 +14,48 @@
#include <sys/stat.h>
// C++ Includes
-#include <sstream>
#include <numeric>
+#include <sstream>
// Other libraries and framework includes
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/Triple.h"
-#include "lldb/Interpreter/Args.h"
+#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/State.h"
#include "lldb/Core/StreamGDBRemote.h"
#include "lldb/Core/StreamString.h"
-#include "lldb/Host/ConnectionFileDescriptor.h"
-#include "lldb/Host/Endian.h"
-#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Host/TimeValue.h"
+#include "lldb/Interpreter/Args.h"
#include "lldb/Symbol/Symbol.h"
-#include "lldb/Target/Target.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/Target.h"
#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/JSON.h"
+#include "lldb/Utility/LLDBAssert.h"
// Project includes
-#include "Utility/StringExtractorGDBRemote.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
+#include "Utility/StringExtractorGDBRemote.h"
#include "lldb/Host/Config.h"
-#if defined (HAVE_LIBCOMPRESSION)
+#include "llvm/ADT/StringSwitch.h"
+
+#if defined(HAVE_LIBCOMPRESSION)
#include <compression.h>
#endif
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
+using namespace std::chrono;
//----------------------------------------------------------------------
// GDBRemoteCommunicationClient constructor
//----------------------------------------------------------------------
GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
- : GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"),
+ : GDBRemoteClientBase("gdb-remote.client", "gdb-remote.client.rx_packet"),
m_supports_not_sending_acks(eLazyBoolCalculate),
m_supports_thread_suffix(eLazyBoolCalculate),
m_supports_threads_in_stop_reply(eLazyBoolCalculate),
@@ -77,8 +76,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_watchpoints_trigger_after_instruction(eLazyBoolCalculate),
m_attach_or_wait_reply(eLazyBoolCalculate),
m_prepare_for_reg_writing_reply(eLazyBoolCalculate),
- m_supports_p(eLazyBoolCalculate),
- m_supports_x(eLazyBoolCalculate),
+ m_supports_p(eLazyBoolCalculate), m_supports_x(eLazyBoolCalculate),
m_avoid_g_packets(eLazyBoolCalculate),
m_supports_QSaveRegisterState(eLazyBoolCalculate),
m_supports_qXfer_auxv_read(eLazyBoolCalculate),
@@ -88,503 +86,449 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate),
m_supports_jThreadExtendedInfo(eLazyBoolCalculate),
m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate),
- m_supports_qProcessInfoPID(true),
- m_supports_qfProcessInfo(true),
- m_supports_qUserName(true),
- m_supports_qGroupName(true),
- m_supports_qThreadStopInfo(true),
- m_supports_z0(true),
- m_supports_z1(true),
- m_supports_z2(true),
- m_supports_z3(true),
- m_supports_z4(true),
- m_supports_QEnvironment(true),
- m_supports_QEnvironmentHexEncoded(true),
- m_supports_qSymbol(true),
- m_qSymbol_requests_done(false),
- m_supports_qModuleInfo(true),
- m_supports_jThreadsInfo(true),
- m_curr_pid(LLDB_INVALID_PROCESS_ID),
- m_curr_tid(LLDB_INVALID_THREAD_ID),
+ m_supports_jGetSharedCacheInfo(eLazyBoolCalculate),
+ m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true),
+ m_supports_qUserName(true), m_supports_qGroupName(true),
+ m_supports_qThreadStopInfo(true), m_supports_z0(true),
+ m_supports_z1(true), m_supports_z2(true), m_supports_z3(true),
+ m_supports_z4(true), m_supports_QEnvironment(true),
+ m_supports_QEnvironmentHexEncoded(true), m_supports_qSymbol(true),
+ m_qSymbol_requests_done(false), m_supports_qModuleInfo(true),
+ m_supports_jThreadsInfo(true), m_supports_jModulesInfo(true),
+ m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID),
m_curr_tid_run(LLDB_INVALID_THREAD_ID),
- m_num_supported_hardware_watchpoints(0),
- m_async_mutex(),
- m_async_packet_predicate(false),
- m_async_packet(),
- m_async_result(PacketResult::Success),
- m_async_response(),
- m_async_signal(-1),
- m_interrupt_sent(false),
- m_thread_id_to_used_usec_map(),
- m_host_arch(),
- m_process_arch(),
- m_os_version_major(UINT32_MAX),
- m_os_version_minor(UINT32_MAX),
- m_os_version_update(UINT32_MAX),
- m_os_build(),
- m_os_kernel(),
- m_hostname(),
- m_gdb_server_name(),
- m_gdb_server_version(UINT32_MAX),
- m_default_packet_timeout(0),
- m_max_packet_size(0)
-{
-}
+ m_num_supported_hardware_watchpoints(0), m_host_arch(), m_process_arch(),
+ m_os_version_major(UINT32_MAX), m_os_version_minor(UINT32_MAX),
+ m_os_version_update(UINT32_MAX), m_os_build(), m_os_kernel(),
+ m_hostname(), m_gdb_server_name(), m_gdb_server_version(UINT32_MAX),
+ m_default_packet_timeout(0), m_max_packet_size(0),
+ m_qSupported_response(), m_supported_async_json_packets_is_valid(false),
+ m_supported_async_json_packets_sp() {}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient()
-{
- if (IsConnected())
- Disconnect();
-}
-
-bool
-GDBRemoteCommunicationClient::HandshakeWithServer (Error *error_ptr)
-{
- ResetDiscoverableSettings(false);
-
- // Start the read thread after we send the handshake ack since if we
- // fail to send the handshake ack, there is no reason to continue...
- if (SendAck())
- {
- // Wait for any responses that might have been queued up in the remote
- // GDB server and flush them all
- StringExtractorGDBRemote response;
- PacketResult packet_result = PacketResult::Success;
- const uint32_t timeout_usec = 10 * 1000; // Wait for 10 ms for a response
- while (packet_result == PacketResult::Success)
- packet_result = ReadPacket (response, timeout_usec, false);
-
- // The return value from QueryNoAckModeSupported() is true if the packet
- // was sent and _any_ response (including UNIMPLEMENTED) was received),
- // or false if no response was received. This quickly tells us if we have
- // a live connection to a remote GDB server...
- if (QueryNoAckModeSupported())
- {
- return true;
- }
- else
- {
- if (error_ptr)
- error_ptr->SetErrorString("failed to get reply to handshake packet");
- }
- }
- else
- {
- if (error_ptr)
- error_ptr->SetErrorString("failed to send the handshake ack");
- }
- return false;
+GDBRemoteCommunicationClient::~GDBRemoteCommunicationClient() {
+ if (IsConnected())
+ Disconnect();
}
-bool
-GDBRemoteCommunicationClient::GetEchoSupported ()
-{
- if (m_supports_qEcho == eLazyBoolCalculate)
- {
- GetRemoteQSupported();
- }
- return m_supports_qEcho == eLazyBoolYes;
-}
+bool GDBRemoteCommunicationClient::HandshakeWithServer(Error *error_ptr) {
+ ResetDiscoverableSettings(false);
+ // Start the read thread after we send the handshake ack since if we
+ // fail to send the handshake ack, there is no reason to continue...
+ if (SendAck()) {
+ // Wait for any responses that might have been queued up in the remote
+ // GDB server and flush them all
+ StringExtractorGDBRemote response;
+ PacketResult packet_result = PacketResult::Success;
+ while (packet_result == PacketResult::Success)
+ packet_result = ReadPacket(response, milliseconds(10), false);
-bool
-GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported ()
-{
- if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate)
- {
- GetRemoteQSupported();
+ // The return value from QueryNoAckModeSupported() is true if the packet
+ // was sent and _any_ response (including UNIMPLEMENTED) was received),
+ // or false if no response was received. This quickly tells us if we have
+ // a live connection to a remote GDB server...
+ if (QueryNoAckModeSupported()) {
+ return true;
+ } else {
+ if (error_ptr)
+ error_ptr->SetErrorString("failed to get reply to handshake packet");
}
- return m_supports_augmented_libraries_svr4_read == eLazyBoolYes;
+ } else {
+ if (error_ptr)
+ error_ptr->SetErrorString("failed to send the handshake ack");
+ }
+ return false;
}
-bool
-GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported ()
-{
- if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate)
- {
- GetRemoteQSupported();
- }
- return m_supports_qXfer_libraries_svr4_read == eLazyBoolYes;
+bool GDBRemoteCommunicationClient::GetEchoSupported() {
+ if (m_supports_qEcho == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_qEcho == eLazyBoolYes;
}
-bool
-GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported ()
-{
- if (m_supports_qXfer_libraries_read == eLazyBoolCalculate)
- {
- GetRemoteQSupported();
- }
- return m_supports_qXfer_libraries_read == eLazyBoolYes;
+bool GDBRemoteCommunicationClient::GetAugmentedLibrariesSVR4ReadSupported() {
+ if (m_supports_augmented_libraries_svr4_read == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_augmented_libraries_svr4_read == eLazyBoolYes;
}
-bool
-GDBRemoteCommunicationClient::GetQXferAuxvReadSupported ()
-{
- if (m_supports_qXfer_auxv_read == eLazyBoolCalculate)
- {
- GetRemoteQSupported();
- }
- return m_supports_qXfer_auxv_read == eLazyBoolYes;
+bool GDBRemoteCommunicationClient::GetQXferLibrariesSVR4ReadSupported() {
+ if (m_supports_qXfer_libraries_svr4_read == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_qXfer_libraries_svr4_read == eLazyBoolYes;
}
-bool
-GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported ()
-{
- if (m_supports_qXfer_features_read == eLazyBoolCalculate)
- {
- GetRemoteQSupported();
- }
- return m_supports_qXfer_features_read == eLazyBoolYes;
+bool GDBRemoteCommunicationClient::GetQXferLibrariesReadSupported() {
+ if (m_supports_qXfer_libraries_read == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_qXfer_libraries_read == eLazyBoolYes;
}
-uint64_t
-GDBRemoteCommunicationClient::GetRemoteMaxPacketSize()
-{
- if (m_max_packet_size == 0)
- {
- GetRemoteQSupported();
- }
- return m_max_packet_size;
+bool GDBRemoteCommunicationClient::GetQXferAuxvReadSupported() {
+ if (m_supports_qXfer_auxv_read == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_qXfer_auxv_read == eLazyBoolYes;
}
-bool
-GDBRemoteCommunicationClient::QueryNoAckModeSupported ()
-{
- if (m_supports_not_sending_acks == eLazyBoolCalculate)
- {
- m_send_acks = true;
- m_supports_not_sending_acks = eLazyBoolNo;
-
- // This is the first real packet that we'll send in a debug session and it may take a little
- // longer than normal to receive a reply. Wait at least 6 seconds for a reply to this packet.
-
- const uint32_t minimum_timeout = 6;
- uint32_t old_timeout = GetPacketTimeoutInMicroSeconds() / lldb_private::TimeValue::MicroSecPerSec;
- GDBRemoteCommunication::ScopedTimeout timeout (*this, std::max (old_timeout, minimum_timeout));
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- {
- m_send_acks = false;
- m_supports_not_sending_acks = eLazyBoolYes;
- }
- return true;
- }
- }
- return false;
+bool GDBRemoteCommunicationClient::GetQXferFeaturesReadSupported() {
+ if (m_supports_qXfer_features_read == eLazyBoolCalculate) {
+ GetRemoteQSupported();
+ }
+ return m_supports_qXfer_features_read == eLazyBoolYes;
}
-void
-GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported ()
-{
- if (m_supports_threads_in_stop_reply == eLazyBoolCalculate)
- {
- m_supports_threads_in_stop_reply = eLazyBoolNo;
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- m_supports_threads_in_stop_reply = eLazyBoolYes;
- }
- }
+uint64_t GDBRemoteCommunicationClient::GetRemoteMaxPacketSize() {
+ if (m_max_packet_size == 0) {
+ GetRemoteQSupported();
+ }
+ return m_max_packet_size;
}
-bool
-GDBRemoteCommunicationClient::GetVAttachOrWaitSupported ()
-{
- if (m_attach_or_wait_reply == eLazyBoolCalculate)
- {
- m_attach_or_wait_reply = eLazyBoolNo;
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- m_attach_or_wait_reply = eLazyBoolYes;
- }
- }
- if (m_attach_or_wait_reply == eLazyBoolYes)
- return true;
- else
- return false;
-}
+bool GDBRemoteCommunicationClient::QueryNoAckModeSupported() {
+ if (m_supports_not_sending_acks == eLazyBoolCalculate) {
+ m_send_acks = true;
+ m_supports_not_sending_acks = eLazyBoolNo;
-bool
-GDBRemoteCommunicationClient::GetSyncThreadStateSupported ()
-{
- if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate)
- {
- m_prepare_for_reg_writing_reply = eLazyBoolNo;
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- m_prepare_for_reg_writing_reply = eLazyBoolYes;
- }
+ // This is the first real packet that we'll send in a debug session and it
+ // may take a little
+ // longer than normal to receive a reply. Wait at least 6 seconds for a
+ // reply to this packet.
+
+ ScopedTimeout timeout(*this, std::max(GetPacketTimeout(), seconds(6)));
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("QStartNoAckMode", response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_send_acks = false;
+ m_supports_not_sending_acks = eLazyBoolYes;
+ }
+ return true;
}
- if (m_prepare_for_reg_writing_reply == eLazyBoolYes)
- return true;
- else
- return false;
+ }
+ return false;
}
+void GDBRemoteCommunicationClient::GetListThreadsInStopReplySupported() {
+ if (m_supports_threads_in_stop_reply == eLazyBoolCalculate) {
+ m_supports_threads_in_stop_reply = eLazyBoolNo;
-void
-GDBRemoteCommunicationClient::ResetDiscoverableSettings (bool did_exec)
-{
- if (did_exec == false)
- {
- // Hard reset everything, this is when we first connect to a GDB server
- m_supports_not_sending_acks = eLazyBoolCalculate;
- m_supports_thread_suffix = eLazyBoolCalculate;
- m_supports_threads_in_stop_reply = eLazyBoolCalculate;
- m_supports_vCont_c = eLazyBoolCalculate;
- m_supports_vCont_C = eLazyBoolCalculate;
- m_supports_vCont_s = eLazyBoolCalculate;
- m_supports_vCont_S = eLazyBoolCalculate;
- m_supports_p = eLazyBoolCalculate;
- m_supports_x = eLazyBoolCalculate;
- m_supports_QSaveRegisterState = eLazyBoolCalculate;
- m_qHostInfo_is_valid = eLazyBoolCalculate;
- m_curr_pid_is_valid = eLazyBoolCalculate;
- m_qGDBServerVersion_is_valid = eLazyBoolCalculate;
- m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
- m_supports_memory_region_info = eLazyBoolCalculate;
- m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
- m_attach_or_wait_reply = eLazyBoolCalculate;
- m_avoid_g_packets = eLazyBoolCalculate;
- m_supports_qXfer_auxv_read = eLazyBoolCalculate;
- m_supports_qXfer_libraries_read = eLazyBoolCalculate;
- m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
- m_supports_qXfer_features_read = eLazyBoolCalculate;
- m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
- m_supports_qProcessInfoPID = true;
- m_supports_qfProcessInfo = true;
- m_supports_qUserName = true;
- m_supports_qGroupName = true;
- m_supports_qThreadStopInfo = true;
- m_supports_z0 = true;
- m_supports_z1 = true;
- m_supports_z2 = true;
- m_supports_z3 = true;
- m_supports_z4 = true;
- m_supports_QEnvironment = true;
- m_supports_QEnvironmentHexEncoded = true;
- m_supports_qSymbol = true;
- m_qSymbol_requests_done = false;
- m_supports_qModuleInfo = true;
- m_host_arch.Clear();
- m_os_version_major = UINT32_MAX;
- m_os_version_minor = UINT32_MAX;
- m_os_version_update = UINT32_MAX;
- m_os_build.clear();
- m_os_kernel.clear();
- m_hostname.clear();
- m_gdb_server_name.clear();
- m_gdb_server_version = UINT32_MAX;
- m_default_packet_timeout = 0;
- m_max_packet_size = 0;
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("QListThreadsInStopReply", response,
+ false) == PacketResult::Success) {
+ if (response.IsOKResponse())
+ m_supports_threads_in_stop_reply = eLazyBoolYes;
}
-
- // These flags should be reset when we first connect to a GDB server
- // and when our inferior process execs
- m_qProcessInfo_is_valid = eLazyBoolCalculate;
- m_process_arch.Clear();
+ }
}
-void
-GDBRemoteCommunicationClient::GetRemoteQSupported ()
-{
- // Clear out any capabilities we expect to see in the qSupported response
- m_supports_qXfer_auxv_read = eLazyBoolNo;
- m_supports_qXfer_libraries_read = eLazyBoolNo;
- m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
- m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
- m_supports_qXfer_features_read = eLazyBoolNo;
- m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if not, we assume no limit
-
- // build the qSupported packet
- std::vector<std::string> features = {"xmlRegisters=i386,arm,mips"};
- StreamString packet;
- packet.PutCString( "qSupported" );
- for ( uint32_t i = 0; i < features.size( ); ++i )
- {
- packet.PutCString( i==0 ? ":" : ";");
- packet.PutCString( features[i].c_str( ) );
- }
+bool GDBRemoteCommunicationClient::GetVAttachOrWaitSupported() {
+ if (m_attach_or_wait_reply == eLazyBoolCalculate) {
+ m_attach_or_wait_reply = eLazyBoolNo;
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet.GetData(),
- response,
- /*send_async=*/false) == PacketResult::Success)
- {
- const char *response_cstr = response.GetStringRef().c_str();
- if (::strstr (response_cstr, "qXfer:auxv:read+"))
- m_supports_qXfer_auxv_read = eLazyBoolYes;
- if (::strstr (response_cstr, "qXfer:libraries-svr4:read+"))
- m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
- if (::strstr (response_cstr, "augmented-libraries-svr4-read"))
- {
- m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
- m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
- }
- if (::strstr (response_cstr, "qXfer:libraries:read+"))
- m_supports_qXfer_libraries_read = eLazyBoolYes;
- if (::strstr (response_cstr, "qXfer:features:read+"))
- m_supports_qXfer_features_read = eLazyBoolYes;
-
-
- // Look for a list of compressions in the features list e.g.
- // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-deflate,lzma
- const char *features_list = ::strstr (response_cstr, "qXfer:features:");
- if (features_list)
- {
- const char *compressions = ::strstr (features_list, "SupportedCompressions=");
- if (compressions)
- {
- std::vector<std::string> supported_compressions;
- compressions += sizeof ("SupportedCompressions=") - 1;
- const char *end_of_compressions = strchr (compressions, ';');
- if (end_of_compressions == NULL)
- {
- end_of_compressions = strchr (compressions, '\0');
- }
- const char *current_compression = compressions;
- while (current_compression < end_of_compressions)
- {
- const char *next_compression_name = strchr (current_compression, ',');
- const char *end_of_this_word = next_compression_name;
- if (next_compression_name == NULL || end_of_compressions < next_compression_name)
- {
- end_of_this_word = end_of_compressions;
- }
-
- if (end_of_this_word)
- {
- if (end_of_this_word == current_compression)
- {
- current_compression++;
- }
- else
- {
- std::string this_compression (current_compression, end_of_this_word - current_compression);
- supported_compressions.push_back (this_compression);
- current_compression = end_of_this_word + 1;
- }
- }
- else
- {
- supported_compressions.push_back (current_compression);
- current_compression = end_of_compressions;
- }
- }
+ if (SendPacketAndWaitForResponse("qVAttachOrWaitSupported", response,
+ false) == PacketResult::Success) {
+ if (response.IsOKResponse())
+ m_attach_or_wait_reply = eLazyBoolYes;
+ }
+ }
+ if (m_attach_or_wait_reply == eLazyBoolYes)
+ return true;
+ else
+ return false;
+}
- if (supported_compressions.size() > 0)
- {
- MaybeEnableCompression (supported_compressions);
- }
- }
- }
+bool GDBRemoteCommunicationClient::GetSyncThreadStateSupported() {
+ if (m_prepare_for_reg_writing_reply == eLazyBoolCalculate) {
+ m_prepare_for_reg_writing_reply = eLazyBoolNo;
- if (::strstr (response_cstr, "qEcho"))
- m_supports_qEcho = eLazyBoolYes;
- else
- m_supports_qEcho = eLazyBoolNo;
-
- const char *packet_size_str = ::strstr (response_cstr, "PacketSize=");
- if (packet_size_str)
- {
- StringExtractorGDBRemote packet_response(packet_size_str + strlen("PacketSize="));
- m_max_packet_size = packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
- if (m_max_packet_size == 0)
- {
- m_max_packet_size = UINT64_MAX; // Must have been a garbled response
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("Garbled PacketSize spec in qSupported response");
- }
- }
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qSyncThreadStateSupported", response,
+ false) == PacketResult::Success) {
+ if (response.IsOKResponse())
+ m_prepare_for_reg_writing_reply = eLazyBoolYes;
}
+ }
+ if (m_prepare_for_reg_writing_reply == eLazyBoolYes)
+ return true;
+ else
+ return false;
}
-bool
-GDBRemoteCommunicationClient::GetThreadSuffixSupported ()
-{
- if (m_supports_thread_suffix == eLazyBoolCalculate)
- {
- StringExtractorGDBRemote response;
- m_supports_thread_suffix = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- m_supports_thread_suffix = eLazyBoolYes;
- }
+void GDBRemoteCommunicationClient::ResetDiscoverableSettings(bool did_exec) {
+ if (did_exec == false) {
+ // Hard reset everything, this is when we first connect to a GDB server
+ m_supports_not_sending_acks = eLazyBoolCalculate;
+ m_supports_thread_suffix = eLazyBoolCalculate;
+ m_supports_threads_in_stop_reply = eLazyBoolCalculate;
+ m_supports_vCont_c = eLazyBoolCalculate;
+ m_supports_vCont_C = eLazyBoolCalculate;
+ m_supports_vCont_s = eLazyBoolCalculate;
+ m_supports_vCont_S = eLazyBoolCalculate;
+ m_supports_p = eLazyBoolCalculate;
+ m_supports_x = eLazyBoolCalculate;
+ m_supports_QSaveRegisterState = eLazyBoolCalculate;
+ m_qHostInfo_is_valid = eLazyBoolCalculate;
+ m_curr_pid_is_valid = eLazyBoolCalculate;
+ m_qGDBServerVersion_is_valid = eLazyBoolCalculate;
+ m_supports_alloc_dealloc_memory = eLazyBoolCalculate;
+ m_supports_memory_region_info = eLazyBoolCalculate;
+ m_prepare_for_reg_writing_reply = eLazyBoolCalculate;
+ m_attach_or_wait_reply = eLazyBoolCalculate;
+ m_avoid_g_packets = eLazyBoolCalculate;
+ m_supports_qXfer_auxv_read = eLazyBoolCalculate;
+ m_supports_qXfer_libraries_read = eLazyBoolCalculate;
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate;
+ m_supports_qXfer_features_read = eLazyBoolCalculate;
+ m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate;
+ m_supports_qProcessInfoPID = true;
+ m_supports_qfProcessInfo = true;
+ m_supports_qUserName = true;
+ m_supports_qGroupName = true;
+ m_supports_qThreadStopInfo = true;
+ m_supports_z0 = true;
+ m_supports_z1 = true;
+ m_supports_z2 = true;
+ m_supports_z3 = true;
+ m_supports_z4 = true;
+ m_supports_QEnvironment = true;
+ m_supports_QEnvironmentHexEncoded = true;
+ m_supports_qSymbol = true;
+ m_qSymbol_requests_done = false;
+ m_supports_qModuleInfo = true;
+ m_host_arch.Clear();
+ m_os_version_major = UINT32_MAX;
+ m_os_version_minor = UINT32_MAX;
+ m_os_version_update = UINT32_MAX;
+ m_os_build.clear();
+ m_os_kernel.clear();
+ m_hostname.clear();
+ m_gdb_server_name.clear();
+ m_gdb_server_version = UINT32_MAX;
+ m_default_packet_timeout = seconds(0);
+ m_max_packet_size = 0;
+ m_qSupported_response.clear();
+ m_supported_async_json_packets_is_valid = false;
+ m_supported_async_json_packets_sp.reset();
+ m_supports_jModulesInfo = true;
+ }
+
+ // These flags should be reset when we first connect to a GDB server
+ // and when our inferior process execs
+ m_qProcessInfo_is_valid = eLazyBoolCalculate;
+ m_process_arch.Clear();
+}
+
+void GDBRemoteCommunicationClient::GetRemoteQSupported() {
+ // Clear out any capabilities we expect to see in the qSupported response
+ m_supports_qXfer_auxv_read = eLazyBoolNo;
+ m_supports_qXfer_libraries_read = eLazyBoolNo;
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolNo;
+ m_supports_augmented_libraries_svr4_read = eLazyBoolNo;
+ m_supports_qXfer_features_read = eLazyBoolNo;
+ m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if
+ // not, we assume no limit
+
+ // build the qSupported packet
+ std::vector<std::string> features = {"xmlRegisters=i386,arm,mips"};
+ StreamString packet;
+ packet.PutCString("qSupported");
+ for (uint32_t i = 0; i < features.size(); ++i) {
+ packet.PutCString(i == 0 ? ":" : ";");
+ packet.PutCString(features[i]);
+ }
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response,
+ /*send_async=*/false) ==
+ PacketResult::Success) {
+ const char *response_cstr = response.GetStringRef().c_str();
+
+ // Hang on to the qSupported packet, so that platforms can do custom
+ // configuration of the transport before attaching/launching the
+ // process.
+ m_qSupported_response = response_cstr;
+
+ if (::strstr(response_cstr, "qXfer:auxv:read+"))
+ m_supports_qXfer_auxv_read = eLazyBoolYes;
+ if (::strstr(response_cstr, "qXfer:libraries-svr4:read+"))
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolYes;
+ if (::strstr(response_cstr, "augmented-libraries-svr4-read")) {
+ m_supports_qXfer_libraries_svr4_read = eLazyBoolYes; // implied
+ m_supports_augmented_libraries_svr4_read = eLazyBoolYes;
+ }
+ if (::strstr(response_cstr, "qXfer:libraries:read+"))
+ m_supports_qXfer_libraries_read = eLazyBoolYes;
+ if (::strstr(response_cstr, "qXfer:features:read+"))
+ m_supports_qXfer_features_read = eLazyBoolYes;
+
+ // Look for a list of compressions in the features list e.g.
+ // qXfer:features:read+;PacketSize=20000;qEcho+;SupportedCompressions=zlib-deflate,lzma
+ const char *features_list = ::strstr(response_cstr, "qXfer:features:");
+ if (features_list) {
+ const char *compressions =
+ ::strstr(features_list, "SupportedCompressions=");
+ if (compressions) {
+ std::vector<std::string> supported_compressions;
+ compressions += sizeof("SupportedCompressions=") - 1;
+ const char *end_of_compressions = strchr(compressions, ';');
+ if (end_of_compressions == NULL) {
+ end_of_compressions = strchr(compressions, '\0');
+ }
+ const char *current_compression = compressions;
+ while (current_compression < end_of_compressions) {
+ const char *next_compression_name = strchr(current_compression, ',');
+ const char *end_of_this_word = next_compression_name;
+ if (next_compression_name == NULL ||
+ end_of_compressions < next_compression_name) {
+ end_of_this_word = end_of_compressions;
+ }
+
+ if (end_of_this_word) {
+ if (end_of_this_word == current_compression) {
+ current_compression++;
+ } else {
+ std::string this_compression(
+ current_compression, end_of_this_word - current_compression);
+ supported_compressions.push_back(this_compression);
+ current_compression = end_of_this_word + 1;
+ }
+ } else {
+ supported_compressions.push_back(current_compression);
+ current_compression = end_of_compressions;
+ }
+ }
+
+ if (supported_compressions.size() > 0) {
+ MaybeEnableCompression(supported_compressions);
+ }
+ }
+ }
+
+ if (::strstr(response_cstr, "qEcho"))
+ m_supports_qEcho = eLazyBoolYes;
+ else
+ m_supports_qEcho = eLazyBoolNo;
+
+ const char *packet_size_str = ::strstr(response_cstr, "PacketSize=");
+ if (packet_size_str) {
+ StringExtractorGDBRemote packet_response(packet_size_str +
+ strlen("PacketSize="));
+ m_max_packet_size =
+ packet_response.GetHexMaxU64(/*little_endian=*/false, UINT64_MAX);
+ if (m_max_packet_size == 0) {
+ m_max_packet_size = UINT64_MAX; // Must have been a garbled response
+ Log *log(
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("Garbled PacketSize spec in qSupported response");
+ }
}
- return m_supports_thread_suffix;
+ }
}
-bool
-GDBRemoteCommunicationClient::GetVContSupported (char flavor)
-{
- if (m_supports_vCont_c == eLazyBoolCalculate)
- {
- StringExtractorGDBRemote response;
- m_supports_vCont_any = eLazyBoolNo;
- m_supports_vCont_all = eLazyBoolNo;
- m_supports_vCont_c = eLazyBoolNo;
- m_supports_vCont_C = eLazyBoolNo;
- m_supports_vCont_s = eLazyBoolNo;
- m_supports_vCont_S = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("vCont?", response, false) == PacketResult::Success)
- {
- const char *response_cstr = response.GetStringRef().c_str();
- if (::strstr (response_cstr, ";c"))
- m_supports_vCont_c = eLazyBoolYes;
-
- if (::strstr (response_cstr, ";C"))
- m_supports_vCont_C = eLazyBoolYes;
-
- if (::strstr (response_cstr, ";s"))
- m_supports_vCont_s = eLazyBoolYes;
-
- if (::strstr (response_cstr, ";S"))
- m_supports_vCont_S = eLazyBoolYes;
-
- if (m_supports_vCont_c == eLazyBoolYes &&
- m_supports_vCont_C == eLazyBoolYes &&
- m_supports_vCont_s == eLazyBoolYes &&
- m_supports_vCont_S == eLazyBoolYes)
- {
- m_supports_vCont_all = eLazyBoolYes;
- }
-
- if (m_supports_vCont_c == eLazyBoolYes ||
- m_supports_vCont_C == eLazyBoolYes ||
- m_supports_vCont_s == eLazyBoolYes ||
- m_supports_vCont_S == eLazyBoolYes)
- {
- m_supports_vCont_any = eLazyBoolYes;
- }
- }
- }
-
- switch (flavor)
- {
- case 'a': return m_supports_vCont_any;
- case 'A': return m_supports_vCont_all;
- case 'c': return m_supports_vCont_c;
- case 'C': return m_supports_vCont_C;
- case 's': return m_supports_vCont_s;
- case 'S': return m_supports_vCont_S;
- default: break;
+
+bool GDBRemoteCommunicationClient::GetThreadSuffixSupported() {
+ if (m_supports_thread_suffix == eLazyBoolCalculate) {
+ StringExtractorGDBRemote response;
+ m_supports_thread_suffix = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("QThreadSuffixSupported", response,
+ false) == PacketResult::Success) {
+ if (response.IsOKResponse())
+ m_supports_thread_suffix = eLazyBoolYes;
}
- return false;
+ }
+ return m_supports_thread_suffix;
+}
+bool GDBRemoteCommunicationClient::GetVContSupported(char flavor) {
+ if (m_supports_vCont_c == eLazyBoolCalculate) {
+ StringExtractorGDBRemote response;
+ m_supports_vCont_any = eLazyBoolNo;
+ m_supports_vCont_all = eLazyBoolNo;
+ m_supports_vCont_c = eLazyBoolNo;
+ m_supports_vCont_C = eLazyBoolNo;
+ m_supports_vCont_s = eLazyBoolNo;
+ m_supports_vCont_S = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("vCont?", response, false) ==
+ PacketResult::Success) {
+ const char *response_cstr = response.GetStringRef().c_str();
+ if (::strstr(response_cstr, ";c"))
+ m_supports_vCont_c = eLazyBoolYes;
+
+ if (::strstr(response_cstr, ";C"))
+ m_supports_vCont_C = eLazyBoolYes;
+
+ if (::strstr(response_cstr, ";s"))
+ m_supports_vCont_s = eLazyBoolYes;
+
+ if (::strstr(response_cstr, ";S"))
+ m_supports_vCont_S = eLazyBoolYes;
+
+ if (m_supports_vCont_c == eLazyBoolYes &&
+ m_supports_vCont_C == eLazyBoolYes &&
+ m_supports_vCont_s == eLazyBoolYes &&
+ m_supports_vCont_S == eLazyBoolYes) {
+ m_supports_vCont_all = eLazyBoolYes;
+ }
+
+ if (m_supports_vCont_c == eLazyBoolYes ||
+ m_supports_vCont_C == eLazyBoolYes ||
+ m_supports_vCont_s == eLazyBoolYes ||
+ m_supports_vCont_S == eLazyBoolYes) {
+ m_supports_vCont_any = eLazyBoolYes;
+ }
+ }
+ }
+
+ switch (flavor) {
+ case 'a':
+ return m_supports_vCont_any;
+ case 'A':
+ return m_supports_vCont_all;
+ case 'c':
+ return m_supports_vCont_c;
+ case 'C':
+ return m_supports_vCont_C;
+ case 's':
+ return m_supports_vCont_s;
+ case 'S':
+ return m_supports_vCont_S;
+ default:
+ break;
+ }
+ return false;
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationClient::SendThreadSpecificPacketAndWaitForResponse(
+ lldb::tid_t tid, StreamString &&payload, StringExtractorGDBRemote &response,
+ bool send_async) {
+ Lock lock(*this, send_async);
+ if (!lock) {
+ if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(
+ GDBR_LOG_PROCESS | GDBR_LOG_PACKETS))
+ log->Printf("GDBRemoteCommunicationClient::%s: Didn't get sequence mutex "
+ "for %s packet.",
+ __FUNCTION__, payload.GetData());
+ return PacketResult::ErrorNoSequenceLock;
+ }
+
+ if (GetThreadSuffixSupported())
+ payload.Printf(";thread:%4.4" PRIx64 ";", tid);
+ else {
+ if (!SetCurrentThread(tid))
+ return PacketResult::ErrorSendFailed;
+ }
+
+ return SendPacketAndWaitForResponseNoLock(payload.GetString(), response);
}
// Check if the target supports 'p' packet. It sends out a 'p'
@@ -592,4043 +536,3095 @@ GDBRemoteCommunicationClient::GetVContSupported (char flavor)
// that support is available.
//
// Takes a valid thread ID because p needs to apply to a thread.
-bool
-GDBRemoteCommunicationClient::GetpPacketSupported (lldb::tid_t tid)
-{
- if (m_supports_p == eLazyBoolCalculate)
- {
- StringExtractorGDBRemote response;
- m_supports_p = eLazyBoolNo;
- char packet[256];
- if (GetThreadSuffixSupported())
- snprintf(packet, sizeof(packet), "p0;thread:%" PRIx64 ";", tid);
- else
- snprintf(packet, sizeof(packet), "p0");
-
- if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
- {
- if (response.IsNormalResponse())
- m_supports_p = eLazyBoolYes;
- }
- }
- return m_supports_p;
-}
-
-StructuredData::ObjectSP
-GDBRemoteCommunicationClient::GetThreadsInfo()
-{
- // Get information on all threads at one using the "jThreadsInfo" packet
- StructuredData::ObjectSP object_sp;
-
- if (m_supports_jThreadsInfo)
- {
- StringExtractorGDBRemote response;
- response.SetResponseValidatorToJSON();
- if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) == PacketResult::Success)
- {
- if (response.IsUnsupportedResponse())
- {
- m_supports_jThreadsInfo = false;
- }
- else if (!response.Empty())
- {
- object_sp = StructuredData::ParseJSON (response.GetStringRef());
- }
- }
+bool GDBRemoteCommunicationClient::GetpPacketSupported(lldb::tid_t tid) {
+ if (m_supports_p == eLazyBoolCalculate) {
+ m_supports_p = eLazyBoolNo;
+ StreamString payload;
+ payload.PutCString("p0");
+ StringExtractorGDBRemote response;
+ if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
+ response, false) ==
+ PacketResult::Success &&
+ response.IsNormalResponse()) {
+ m_supports_p = eLazyBoolYes;
}
- return object_sp;
+ }
+ return m_supports_p;
}
+StructuredData::ObjectSP GDBRemoteCommunicationClient::GetThreadsInfo() {
+ // Get information on all threads at one using the "jThreadsInfo" packet
+ StructuredData::ObjectSP object_sp;
-bool
-GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported ()
-{
- if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate)
- {
- StringExtractorGDBRemote response;
- m_supports_jThreadExtendedInfo = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- {
- m_supports_jThreadExtendedInfo = eLazyBoolYes;
- }
- }
+ if (m_supports_jThreadsInfo) {
+ StringExtractorGDBRemote response;
+ response.SetResponseValidatorToJSON();
+ if (SendPacketAndWaitForResponse("jThreadsInfo", response, false) ==
+ PacketResult::Success) {
+ if (response.IsUnsupportedResponse()) {
+ m_supports_jThreadsInfo = false;
+ } else if (!response.Empty()) {
+ object_sp = StructuredData::ParseJSON(response.GetStringRef());
+ }
}
- return m_supports_jThreadExtendedInfo;
+ }
+ return object_sp;
}
-bool
-GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported ()
-{
- if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate)
- {
- StringExtractorGDBRemote response;
- m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo;
- if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:", response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- {
- m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes;
- }
- }
+bool GDBRemoteCommunicationClient::GetThreadExtendedInfoSupported() {
+ if (m_supports_jThreadExtendedInfo == eLazyBoolCalculate) {
+ StringExtractorGDBRemote response;
+ m_supports_jThreadExtendedInfo = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("jThreadExtendedInfo:", response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_supports_jThreadExtendedInfo = eLazyBoolYes;
+ }
}
- return m_supports_jLoadedDynamicLibrariesInfos;
+ }
+ return m_supports_jThreadExtendedInfo;
}
-bool
-GDBRemoteCommunicationClient::GetxPacketSupported ()
-{
- if (m_supports_x == eLazyBoolCalculate)
- {
- StringExtractorGDBRemote response;
- m_supports_x = eLazyBoolNo;
- char packet[256];
- snprintf (packet, sizeof (packet), "x0,0");
- if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- m_supports_x = eLazyBoolYes;
- }
+bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() {
+ if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) {
+ StringExtractorGDBRemote response;
+ m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("jGetLoadedDynamicLibrariesInfos:",
+ response,
+ false) == PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_supports_jLoadedDynamicLibrariesInfos = eLazyBoolYes;
+ }
}
- return m_supports_x;
+ }
+ return m_supports_jLoadedDynamicLibrariesInfos;
}
-GDBRemoteCommunicationClient::PacketResult
-GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses
-(
- const char *payload_prefix,
- std::string &response_string
-)
-{
- Mutex::Locker locker;
- if (!GetSequenceMutex(locker,
- "ProcessGDBRemote::SendPacketsAndConcatenateResponses() failed due to not getting the sequence mutex"))
- {
- Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
- if (log)
- log->Printf("error: failed to get packet sequence mutex, not sending packets with prefix '%s'",
- payload_prefix);
- return PacketResult::ErrorNoSequenceLock;
- }
-
- response_string = "";
- std::string payload_prefix_str(payload_prefix);
- unsigned int response_size = 0x1000;
- if (response_size > GetRemoteMaxPacketSize()) { // May send qSupported packet
- response_size = GetRemoteMaxPacketSize();
- }
-
- for (unsigned int offset = 0; true; offset += response_size)
- {
- StringExtractorGDBRemote this_response;
- // Construct payload
- char sizeDescriptor[128];
- snprintf(sizeDescriptor, sizeof(sizeDescriptor), "%x,%x", offset, response_size);
- PacketResult result = SendPacketAndWaitForResponse((payload_prefix_str + sizeDescriptor).c_str(),
- this_response,
- /*send_async=*/false);
- if (result != PacketResult::Success)
- return result;
-
- const std::string &this_string = this_response.GetStringRef();
-
- // Check for m or l as first character; l seems to mean this is the last chunk
- char first_char = *this_string.c_str();
- if (first_char != 'm' && first_char != 'l')
- {
- return PacketResult::ErrorReplyInvalid;
- }
- // Concatenate the result so far (skipping 'm' or 'l')
- response_string.append(this_string, 1, std::string::npos);
- if (first_char == 'l')
- // We're done
- return PacketResult::Success;
+bool GDBRemoteCommunicationClient::GetSharedCacheInfoSupported() {
+ if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate) {
+ StringExtractorGDBRemote response;
+ m_supports_jGetSharedCacheInfo = eLazyBoolNo;
+ if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_supports_jGetSharedCacheInfo = eLazyBoolYes;
+ }
}
+ }
+ return m_supports_jGetSharedCacheInfo;
}
-GDBRemoteCommunicationClient::PacketResult
-GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
-(
- const char *payload,
- StringExtractorGDBRemote &response,
- bool send_async
-)
-{
- return SendPacketAndWaitForResponse (payload,
- ::strlen (payload),
- response,
- send_async);
-}
-
-GDBRemoteCommunicationClient::PacketResult
-GDBRemoteCommunicationClient::SendPacketAndWaitForResponseNoLock (const char *payload,
- size_t payload_length,
- StringExtractorGDBRemote &response)
-{
- PacketResult packet_result = SendPacketNoLock(payload, payload_length);
- if (packet_result == PacketResult::Success)
- {
- const size_t max_response_retries = 3;
- for (size_t i=0; i<max_response_retries; ++i)
- {
- packet_result = ReadPacket(response, GetPacketTimeoutInMicroSeconds (), true);
- // Make sure we received a response
- if (packet_result != PacketResult::Success)
- return packet_result;
- // Make sure our response is valid for the payload that was sent
- if (response.ValidateResponse())
- return packet_result;
- // Response says it wasn't valid
- Log *log = ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS);
- if (log)
- log->Printf("error: packet with payload \"%*s\" got invalid response \"%s\": %s",
- (int)payload_length,
- payload,
- response.GetStringRef().c_str(),
- (i == (max_response_retries - 1)) ? "using invalid response and giving up" : "ignoring response and waiting for another");
- }
+bool GDBRemoteCommunicationClient::GetxPacketSupported() {
+ if (m_supports_x == eLazyBoolCalculate) {
+ StringExtractorGDBRemote response;
+ m_supports_x = eLazyBoolNo;
+ char packet[256];
+ snprintf(packet, sizeof(packet), "x0,0");
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ m_supports_x = eLazyBoolYes;
}
- return packet_result;
+ }
+ return m_supports_x;
}
GDBRemoteCommunicationClient::PacketResult
-GDBRemoteCommunicationClient::SendPacketAndWaitForResponse
-(
- const char *payload,
- size_t payload_length,
- StringExtractorGDBRemote &response,
- bool send_async
-)
-{
- PacketResult packet_result = PacketResult::ErrorSendFailed;
- Mutex::Locker locker;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
-
- // In order to stop async notifications from being processed in the middle of the
- // send/receive sequence Hijack the broadcast. Then rebroadcast any events when we are done.
- static ListenerSP hijack_listener_sp(Listener::MakeListener("lldb.NotifyHijacker"));
- HijackBroadcaster(hijack_listener_sp, eBroadcastBitGdbReadThreadGotNotify);
-
- if (GetSequenceMutex (locker))
- {
- packet_result = SendPacketAndWaitForResponseNoLock (payload, payload_length, response);
- }
- else
- {
- if (send_async)
- {
- if (IsRunning())
- {
- std::lock_guard<std::recursive_mutex> guard(m_async_mutex);
- m_async_packet.assign(payload, payload_length);
- m_async_response.CopyResponseValidator(response);
- m_async_packet_predicate.SetValue (true, eBroadcastNever);
-
- if (log)
- log->Printf ("async: async packet = %s", m_async_packet.c_str());
-
- bool timed_out = false;
- if (SendInterrupt(locker, 2, timed_out))
- {
- if (m_interrupt_sent)
- {
- m_interrupt_sent = false;
- TimeValue timeout_time;
- timeout_time = TimeValue::Now();
- timeout_time.OffsetWithSeconds (m_packet_timeout);
-
- if (log)
- log->Printf ("async: sent interrupt");
-
- if (m_async_packet_predicate.WaitForValueEqualTo (false, &timeout_time, &timed_out))
- {
- if (log)
- log->Printf ("async: got response");
-
- // Swap the response buffer to avoid malloc and string copy
- response.GetStringRef().swap (m_async_response.GetStringRef());
- packet_result = m_async_result;
- }
- else
- {
- if (log)
- log->Printf ("async: timed out waiting for response");
- }
-
- // Make sure we wait until the continue packet has been sent again...
- if (m_private_is_running.WaitForValueEqualTo (true, &timeout_time, &timed_out))
- {
- if (log)
- {
- if (timed_out)
- log->Printf ("async: timed out waiting for process to resume, but process was resumed");
- else
- log->Printf ("async: async packet sent");
- }
- }
- else
- {
- if (log)
- log->Printf ("async: timed out waiting for process to resume");
- }
- }
- else
- {
- // We had a racy condition where we went to send the interrupt
- // yet we were able to get the lock, so the process must have
- // just stopped?
- if (log)
- log->Printf ("async: got lock without sending interrupt");
- // Send the packet normally since we got the lock
- packet_result = SendPacketAndWaitForResponseNoLock (payload, payload_length, response);
- }
- }
- else
- {
- if (log)
- log->Printf ("async: failed to interrupt");
- }
-
- m_async_response.SetResponseValidator(nullptr, nullptr);
-
- }
- else
- {
- if (log)
- log->Printf ("async: not running, async is ignored");
- }
- }
- else
- {
- if (log)
- log->Printf("error: failed to get packet sequence mutex, not sending packet '%*s'", (int) payload_length, payload);
- }
- }
-
- // Remove our Hijacking listener from the broadcast.
- RestoreBroadcaster();
-
- // If a notification event occurred, rebroadcast since it can now be processed safely.
- EventSP event_sp;
- if (hijack_listener_sp->GetNextEvent(event_sp))
- BroadcastEvent(event_sp);
-
- return packet_result;
-}
-
-static const char *end_delimiter = "--end--;";
-static const int end_delimiter_len = 8;
-
-std::string
-GDBRemoteCommunicationClient::HarmonizeThreadIdsForProfileData
-( ProcessGDBRemote *process,
- StringExtractorGDBRemote& profileDataExtractor
-)
-{
- std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map;
- std::stringstream final_output;
- std::string name, value;
-
- // Going to assuming thread_used_usec comes first, else bail out.
- while (profileDataExtractor.GetNameColonValue(name, value))
- {
- if (name.compare("thread_used_id") == 0)
- {
- StringExtractor threadIDHexExtractor(value.c_str());
- uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0);
-
- bool has_used_usec = false;
- uint32_t curr_used_usec = 0;
- std::string usec_name, usec_value;
- uint32_t input_file_pos = profileDataExtractor.GetFilePos();
- if (profileDataExtractor.GetNameColonValue(usec_name, usec_value))
- {
- if (usec_name.compare("thread_used_usec") == 0)
- {
- has_used_usec = true;
- curr_used_usec = strtoull(usec_value.c_str(), NULL, 0);
- }
- else
- {
- // We didn't find what we want, it is probably
- // an older version. Bail out.
- profileDataExtractor.SetFilePos(input_file_pos);
- }
- }
-
- if (has_used_usec)
- {
- uint32_t prev_used_usec = 0;
- std::map<uint64_t, uint32_t>::iterator iterator = m_thread_id_to_used_usec_map.find(thread_id);
- if (iterator != m_thread_id_to_used_usec_map.end())
- {
- prev_used_usec = m_thread_id_to_used_usec_map[thread_id];
- }
-
- uint32_t real_used_usec = curr_used_usec - prev_used_usec;
- // A good first time record is one that runs for at least 0.25 sec
- bool good_first_time = (prev_used_usec == 0) && (real_used_usec > 250000);
- bool good_subsequent_time = (prev_used_usec > 0) &&
- ((real_used_usec > 0) || (process->HasAssignedIndexIDToThread(thread_id)));
-
- if (good_first_time || good_subsequent_time)
- {
- // We try to avoid doing too many index id reservation,
- // resulting in fast increase of index ids.
-
- final_output << name << ":";
- int32_t index_id = process->AssignIndexIDToThread(thread_id);
- final_output << index_id << ";";
-
- final_output << usec_name << ":" << usec_value << ";";
- }
- else
- {
- // Skip past 'thread_used_name'.
- std::string local_name, local_value;
- profileDataExtractor.GetNameColonValue(local_name, local_value);
- }
-
- // Store current time as previous time so that they can be compared later.
- new_thread_id_to_used_usec_map[thread_id] = curr_used_usec;
- }
- else
- {
- // Bail out and use old string.
- final_output << name << ":" << value << ";";
- }
- }
- else
- {
- final_output << name << ":" << value << ";";
- }
- }
- final_output << end_delimiter;
- m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map;
-
- return final_output.str();
-}
-
-bool
-GDBRemoteCommunicationClient::SendvContPacket
-(
- ProcessGDBRemote *process,
- const char *payload,
- size_t packet_length,
- StringExtractorGDBRemote &response
-)
-{
-
- m_curr_tid = LLDB_INVALID_THREAD_ID;
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
-
- // we want to lock down packet sending while we continue
- Mutex::Locker locker(m_sequence_mutex);
-
- // here we broadcast this before we even send the packet!!
- // this signals doContinue() to exit
- BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
-
- // set the public state to running
- m_public_is_running.SetValue(true, eBroadcastNever);
-
- // Set the starting continue packet into "continue_packet". This packet
- // may change if we are interrupted and we continue after an async packet...
- std::string continue_packet(payload, packet_length);
-
- if (log)
- log->Printf("GDBRemoteCommunicationClient::%s () sending vCont packet: %s", __FUNCTION__, continue_packet.c_str());
-
- if (SendPacketNoLock(continue_packet.c_str(), continue_packet.size()) != PacketResult::Success)
- return false;
-
- // set the private state to running and broadcast this
- m_private_is_running.SetValue(true, eBroadcastAlways);
-
+GDBRemoteCommunicationClient::SendPacketsAndConcatenateResponses(
+ const char *payload_prefix, std::string &response_string) {
+ Lock lock(*this, false);
+ if (!lock) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
+ GDBR_LOG_PACKETS));
if (log)
- log->Printf("GDBRemoteCommunicationClient::%s () ReadPacket(%s)", __FUNCTION__, continue_packet.c_str());
-
- // wait for the response to the vCont
- if (ReadPacket(response, UINT32_MAX, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return true;
- }
-
- return false;
-}
-
-StateType
-GDBRemoteCommunicationClient::SendContinuePacketAndWaitForResponse
-(
- ProcessGDBRemote *process,
- const char *payload,
- size_t packet_length,
- StringExtractorGDBRemote &response
-)
-{
- m_curr_tid = LLDB_INVALID_THREAD_ID;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("GDBRemoteCommunicationClient::%s ()", __FUNCTION__);
-
- Mutex::Locker locker(m_sequence_mutex);
- StateType state = eStateRunning;
-
- m_public_is_running.SetValue (true, eBroadcastNever);
- // Set the starting continue packet into "continue_packet". This packet
- // may change if we are interrupted and we continue after an async packet...
- std::string continue_packet(payload, packet_length);
-
- const auto sigstop_signo = process->GetUnixSignals()->GetSignalNumberFromName("SIGSTOP");
- const auto sigint_signo = process->GetUnixSignals()->GetSignalNumberFromName("SIGINT");
-
- bool got_async_packet = false;
- bool broadcast_sent = false;
-
- while (state == eStateRunning)
- {
- if (!got_async_packet)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationClient::%s () sending continue packet: %s", __FUNCTION__, continue_packet.c_str());
- if (SendPacketNoLock(continue_packet.c_str(), continue_packet.size()) != PacketResult::Success)
- state = eStateInvalid;
- else
- m_interrupt_sent = false;
-
- if (! broadcast_sent)
- {
- BroadcastEvent(eBroadcastBitRunPacketSent, NULL);
- broadcast_sent = true;
- }
-
- m_private_is_running.SetValue (true, eBroadcastAlways);
- }
-
- got_async_packet = false;
-
- if (log)
- log->Printf ("GDBRemoteCommunicationClient::%s () ReadPacket(%s)", __FUNCTION__, continue_packet.c_str());
-
- if (ReadPacket(response, UINT32_MAX, false) == PacketResult::Success)
- {
- if (response.Empty())
- state = eStateInvalid;
- else
- {
- const char stop_type = response.GetChar();
- if (log)
- log->Printf ("GDBRemoteCommunicationClient::%s () got packet: %s", __FUNCTION__, response.GetStringRef().c_str());
- switch (stop_type)
- {
- case 'T':
- case 'S':
- {
- if (process->GetStopID() == 0)
- {
- if (process->GetID() == LLDB_INVALID_PROCESS_ID)
- {
- lldb::pid_t pid = GetCurrentProcessID ();
- if (pid != LLDB_INVALID_PROCESS_ID)
- process->SetID (pid);
- }
- process->BuildDynamicRegisterInfo (true);
- }
-
- // Privately notify any internal threads that we have stopped
- // in case we wanted to interrupt our process, yet we might
- // send a packet and continue without returning control to the
- // user.
- m_private_is_running.SetValue (false, eBroadcastAlways);
-
- const uint8_t signo = response.GetHexU8 (UINT8_MAX);
-
- bool continue_after_async = m_async_signal != -1 || m_async_packet_predicate.GetValue();
- if (continue_after_async || m_interrupt_sent)
- {
- // We sent an interrupt packet to stop the inferior process
- // for an async signal or to send an async packet while running
- // but we might have been single stepping and received the
- // stop packet for the step instead of for the interrupt packet.
- // Typically when an interrupt is sent a SIGINT or SIGSTOP
- // is used, so if we get anything else, we need to try and
- // get another stop reply packet that may have been sent
- // due to sending the interrupt when the target is stopped
- // which will just re-send a copy of the last stop reply
- // packet. If we don't do this, then the reply for our
- // async packet will be the repeat stop reply packet and cause
- // a lot of trouble for us! We also have some debugserver
- // binaries that would send two stop replies anytime the process
- // was interrupted, so we need to also check for an extra
- // stop reply packet if we interrupted the process
- const bool received_nonstop_signal = signo != sigint_signo && signo != sigstop_signo;
- if (m_interrupt_sent || received_nonstop_signal)
- {
- if (received_nonstop_signal)
- continue_after_async = false;
-
- // Try for a very brief time (0.1s) to get another stop reply
- // packet to make sure it doesn't get in the way
- StringExtractorGDBRemote extra_stop_reply_packet;
- uint32_t timeout_usec = 100000;
- if (ReadPacket (extra_stop_reply_packet, timeout_usec, false) == PacketResult::Success)
- {
- switch (extra_stop_reply_packet.GetChar())
- {
- case 'T':
- case 'S':
- // We did get an extra stop reply, which means
- // our interrupt didn't stop the target so we
- // shouldn't continue after the async signal
- // or packet is sent...
- continue_after_async = false;
- break;
- }
- }
- }
- }
-
- if (m_async_signal != -1)
- {
- if (log)
- log->Printf ("async: send signo = %s", Host::GetSignalAsCString (m_async_signal));
-
- // Save off the async signal we are supposed to send
- const int async_signal = m_async_signal;
- // Clear the async signal member so we don't end up
- // sending the signal multiple times...
- m_async_signal = -1;
- // Check which signal we stopped with
- if (signo == async_signal)
- {
- if (log)
- log->Printf ("async: stopped with signal %s, we are done running", Host::GetSignalAsCString (signo));
-
- // We already stopped with a signal that we wanted
- // to stop with, so we are done
- }
- else
- {
- // We stopped with a different signal that the one
- // we wanted to stop with, so now we must resume
- // with the signal we want
- char signal_packet[32];
- int signal_packet_len = 0;
- signal_packet_len = ::snprintf (signal_packet,
- sizeof (signal_packet),
- "C%2.2x",
- async_signal);
-
- if (log)
- log->Printf ("async: stopped with signal %s, resume with %s",
- Host::GetSignalAsCString (signo),
- Host::GetSignalAsCString (async_signal));
-
- // Set the continue packet to resume even if the
- // interrupt didn't cause our stop (ignore continue_after_async)
- continue_packet.assign(signal_packet, signal_packet_len);
- continue;
- }
- }
- else if (m_async_packet_predicate.GetValue())
- {
- Log * packet_log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PACKETS));
-
- // We are supposed to send an asynchronous packet while
- // we are running.
- m_async_response.Clear();
- if (m_async_packet.empty())
- {
- m_async_result = PacketResult::ErrorSendFailed;
- if (packet_log)
- packet_log->Printf ("async: error: empty async packet");
-
- }
- else
- {
- if (packet_log)
- packet_log->Printf ("async: sending packet");
-
- m_async_result = SendPacketAndWaitForResponse (&m_async_packet[0],
- m_async_packet.size(),
- m_async_response,
- false);
- }
- // Let the other thread that was trying to send the async
- // packet know that the packet has been sent and response is
- // ready...
- m_async_packet_predicate.SetValue(false, eBroadcastAlways);
-
- if (packet_log)
- packet_log->Printf ("async: sent packet, continue_after_async = %i", continue_after_async);
-
- // Set the continue packet to resume if our interrupt
- // for the async packet did cause the stop
- if (continue_after_async)
- {
- // Reverting this for now as it is causing deadlocks
- // in programs (<rdar://problem/11529853>). In the future
- // we should check our thread list and "do the right thing"
- // for new threads that show up while we stop and run async
- // packets. Setting the packet to 'c' to continue all threads
- // is the right thing to do 99.99% of the time because if a
- // thread was single stepping, and we sent an interrupt, we
- // will notice above that we didn't stop due to an interrupt
- // but stopped due to stepping and we would _not_ continue.
- continue_packet.assign (1, 'c');
- continue;
- }
- }
- // Stop with signal and thread info
- state = eStateStopped;
- }
- break;
-
- case 'W':
- case 'X':
- // process exited
- state = eStateExited;
- break;
-
- case 'O':
- // STDOUT
- {
- got_async_packet = true;
- std::string inferior_stdout;
- inferior_stdout.reserve(response.GetBytesLeft () / 2);
-
- uint8_t ch;
- while (response.GetHexU8Ex(ch))
- {
- if (ch != 0)
- inferior_stdout.append(1, (char)ch);
- }
- process->AppendSTDOUT (inferior_stdout.c_str(), inferior_stdout.size());
- }
- break;
-
- case 'A':
- // Async miscellaneous reply. Right now, only profile data is coming through this channel.
- {
- got_async_packet = true;
- std::string input = response.GetStringRef().substr(1); // '1' to move beyond 'A'
- if (m_partial_profile_data.length() > 0)
- {
- m_partial_profile_data.append(input);
- input = m_partial_profile_data;
- m_partial_profile_data.clear();
- }
-
- size_t found, pos = 0, len = input.length();
- while ((found = input.find(end_delimiter, pos)) != std::string::npos)
- {
- StringExtractorGDBRemote profileDataExtractor(input.substr(pos, found).c_str());
- std::string profile_data = HarmonizeThreadIdsForProfileData(process, profileDataExtractor);
- process->BroadcastAsyncProfileData (profile_data);
-
- pos = found + end_delimiter_len;
- }
-
- if (pos < len)
- {
- // Last incomplete chunk.
- m_partial_profile_data = input.substr(pos);
- }
- }
- break;
-
- case 'E':
- // ERROR
- state = eStateInvalid;
- break;
-
- default:
- if (log)
- log->Printf ("GDBRemoteCommunicationClient::%s () unrecognized async packet", __FUNCTION__);
- state = eStateInvalid;
- break;
- }
- }
- }
- else
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationClient::%s () ReadPacket(...) => false", __FUNCTION__);
- state = eStateInvalid;
- }
- }
- if (log)
- log->Printf ("GDBRemoteCommunicationClient::%s () => %s", __FUNCTION__, StateAsCString(state));
- response.SetFilePos(0);
- m_private_is_running.SetValue (false, eBroadcastAlways);
- m_public_is_running.SetValue (false, eBroadcastAlways);
- return state;
-}
-
-bool
-GDBRemoteCommunicationClient::SendAsyncSignal (int signo)
-{
- std::lock_guard<std::recursive_mutex> guard(m_async_mutex);
- m_async_signal = signo;
- bool timed_out = false;
- Mutex::Locker locker;
- if (SendInterrupt (locker, 1, timed_out))
- return true;
- m_async_signal = -1;
- return false;
-}
-
-// This function takes a mutex locker as a parameter in case the GetSequenceMutex
-// actually succeeds. If it doesn't succeed in acquiring the sequence mutex
-// (the expected result), then it will send the halt packet. If it does succeed
-// then the caller that requested the interrupt will want to keep the sequence
-// locked down so that no one else can send packets while the caller has control.
-// This function usually gets called when we are running and need to stop the
-// target. It can also be used when we are running and we need to do something
-// else (like read/write memory), so we need to interrupt the running process
-// (gdb remote protocol requires this), and do what we need to do, then resume.
-
-bool
-GDBRemoteCommunicationClient::SendInterrupt
-(
- Mutex::Locker& locker,
- uint32_t seconds_to_wait_for_stop,
- bool &timed_out
-)
-{
- timed_out = false;
- Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
-
- if (IsRunning())
- {
- // Only send an interrupt if our debugserver is running...
- if (GetSequenceMutex (locker))
- {
- if (log)
- log->Printf ("SendInterrupt () - got sequence mutex without having to interrupt");
- }
- else
- {
- // Someone has the mutex locked waiting for a response or for the
- // inferior to stop, so send the interrupt on the down low...
- char ctrl_c = '\x03';
- ConnectionStatus status = eConnectionStatusSuccess;
- size_t bytes_written = Write (&ctrl_c, 1, status, NULL);
- if (log)
- log->PutCString("send packet: \\x03");
- if (bytes_written > 0)
- {
- m_interrupt_sent = true;
- if (seconds_to_wait_for_stop)
- {
- TimeValue timeout;
- if (seconds_to_wait_for_stop)
- {
- timeout = TimeValue::Now();
- timeout.OffsetWithSeconds (seconds_to_wait_for_stop);
- }
- if (m_private_is_running.WaitForValueEqualTo (false, &timeout, &timed_out))
- {
- if (log)
- log->PutCString ("SendInterrupt () - sent interrupt, private state stopped");
- return true;
- }
- else
- {
- if (log)
- log->Printf ("SendInterrupt () - sent interrupt, timed out wating for async thread resume");
- }
- }
- else
- {
- if (log)
- log->Printf ("SendInterrupt () - sent interrupt, not waiting for stop...");
- return true;
- }
- }
- else
- {
- if (log)
- log->Printf ("SendInterrupt () - failed to write interrupt");
- }
- return false;
- }
- }
- else
- {
- if (log)
- log->Printf ("SendInterrupt () - not running");
- }
- return true;
-}
-
-lldb::pid_t
-GDBRemoteCommunicationClient::GetCurrentProcessID (bool allow_lazy)
-{
- if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes)
- return m_curr_pid;
-
- // First try to retrieve the pid via the qProcessInfo request.
- GetCurrentProcessInfo (allow_lazy);
- if (m_curr_pid_is_valid == eLazyBoolYes)
- {
- // We really got it.
+ log->Printf("error: failed to get packet sequence mutex, not sending "
+ "packets with prefix '%s'",
+ payload_prefix);
+ return PacketResult::ErrorNoSequenceLock;
+ }
+
+ response_string = "";
+ std::string payload_prefix_str(payload_prefix);
+ unsigned int response_size = 0x1000;
+ if (response_size > GetRemoteMaxPacketSize()) { // May send qSupported packet
+ response_size = GetRemoteMaxPacketSize();
+ }
+
+ for (unsigned int offset = 0; true; offset += response_size) {
+ StringExtractorGDBRemote this_response;
+ // Construct payload
+ char sizeDescriptor[128];
+ snprintf(sizeDescriptor, sizeof(sizeDescriptor), "%x,%x", offset,
+ response_size);
+ PacketResult result = SendPacketAndWaitForResponseNoLock(
+ payload_prefix_str + sizeDescriptor, this_response);
+ if (result != PacketResult::Success)
+ return result;
+
+ const std::string &this_string = this_response.GetStringRef();
+
+ // Check for m or l as first character; l seems to mean this is the last
+ // chunk
+ char first_char = *this_string.c_str();
+ if (first_char != 'm' && first_char != 'l') {
+ return PacketResult::ErrorReplyInvalid;
+ }
+ // Concatenate the result so far (skipping 'm' or 'l')
+ response_string.append(this_string, 1, std::string::npos);
+ if (first_char == 'l')
+ // We're done
+ return PacketResult::Success;
+ }
+}
+
+lldb::pid_t GDBRemoteCommunicationClient::GetCurrentProcessID(bool allow_lazy) {
+ if (allow_lazy && m_curr_pid_is_valid == eLazyBoolYes)
+ return m_curr_pid;
+
+ // First try to retrieve the pid via the qProcessInfo request.
+ GetCurrentProcessInfo(allow_lazy);
+ if (m_curr_pid_is_valid == eLazyBoolYes) {
+ // We really got it.
+ return m_curr_pid;
+ } else {
+ // If we don't get a response for qProcessInfo, check if $qC gives us a
+ // result.
+ // $qC only returns a real process id on older debugserver and lldb-platform
+ // stubs.
+ // The gdb remote protocol documents $qC as returning the thread id, which
+ // newer
+ // debugserver and lldb-gdbserver stubs return correctly.
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qC", response, false) ==
+ PacketResult::Success) {
+ if (response.GetChar() == 'Q') {
+ if (response.GetChar() == 'C') {
+ m_curr_pid = response.GetHexMaxU32(false, LLDB_INVALID_PROCESS_ID);
+ if (m_curr_pid != LLDB_INVALID_PROCESS_ID) {
+ m_curr_pid_is_valid = eLazyBoolYes;
+ return m_curr_pid;
+ }
+ }
+ }
+ }
+
+ // If we don't get a response for $qC, check if $qfThreadID gives us a
+ // result.
+ if (m_curr_pid == LLDB_INVALID_PROCESS_ID) {
+ std::vector<lldb::tid_t> thread_ids;
+ bool sequence_mutex_unavailable;
+ size_t size;
+ size = GetCurrentThreadIDs(thread_ids, sequence_mutex_unavailable);
+ if (size && sequence_mutex_unavailable == false) {
+ m_curr_pid = thread_ids.front();
+ m_curr_pid_is_valid = eLazyBoolYes;
return m_curr_pid;
+ }
+ }
+ }
+
+ return LLDB_INVALID_PROCESS_ID;
+}
+
+bool GDBRemoteCommunicationClient::GetLaunchSuccess(std::string &error_str) {
+ error_str.clear();
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qLaunchSuccess", response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return true;
+ if (response.GetChar() == 'E') {
+ // A string the describes what failed when launching...
+ error_str = response.GetStringRef().substr(1);
+ } else {
+ error_str.assign("unknown error occurred launching process");
+ }
+ } else {
+ error_str.assign("timed out waiting for app to launch");
+ }
+ return false;
+}
+
+int GDBRemoteCommunicationClient::SendArgumentsPacket(
+ const ProcessLaunchInfo &launch_info) {
+ // Since we don't get the send argv0 separate from the executable path, we
+ // need to
+ // make sure to use the actual executable path found in the launch_info...
+ std::vector<const char *> argv;
+ FileSpec exe_file = launch_info.GetExecutableFile();
+ std::string exe_path;
+ const char *arg = NULL;
+ const Args &launch_args = launch_info.GetArguments();
+ if (exe_file)
+ exe_path = exe_file.GetPath(false);
+ else {
+ arg = launch_args.GetArgumentAtIndex(0);
+ if (arg)
+ exe_path = arg;
+ }
+ if (!exe_path.empty()) {
+ argv.push_back(exe_path.c_str());
+ for (uint32_t i = 1; (arg = launch_args.GetArgumentAtIndex(i)) != NULL;
+ ++i) {
+ if (arg)
+ argv.push_back(arg);
+ }
+ }
+ if (!argv.empty()) {
+ StreamString packet;
+ packet.PutChar('A');
+ for (size_t i = 0, n = argv.size(); i < n; ++i) {
+ arg = argv[i];
+ const int arg_len = strlen(arg);
+ if (i > 0)
+ packet.PutChar(',');
+ packet.Printf("%i,%i,", arg_len * 2, (int)i);
+ packet.PutBytesAsRawHex8(arg, arg_len);
}
- else
- {
- // If we don't get a response for qProcessInfo, check if $qC gives us a result.
- // $qC only returns a real process id on older debugserver and lldb-platform stubs.
- // The gdb remote protocol documents $qC as returning the thread id, which newer
- // debugserver and lldb-gdbserver stubs return correctly.
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qC", strlen("qC"), response, false) == PacketResult::Success)
- {
- if (response.GetChar() == 'Q')
- {
- if (response.GetChar() == 'C')
- {
- m_curr_pid = response.GetHexMaxU32 (false, LLDB_INVALID_PROCESS_ID);
- if (m_curr_pid != LLDB_INVALID_PROCESS_ID)
- {
- m_curr_pid_is_valid = eLazyBoolYes;
- return m_curr_pid;
- }
- }
- }
- }
-
- // If we don't get a response for $qC, check if $qfThreadID gives us a result.
- if (m_curr_pid == LLDB_INVALID_PROCESS_ID)
- {
- std::vector<lldb::tid_t> thread_ids;
- bool sequence_mutex_unavailable;
- size_t size;
- size = GetCurrentThreadIDs (thread_ids, sequence_mutex_unavailable);
- if (size && sequence_mutex_unavailable == false)
- {
- m_curr_pid = thread_ids.front();
- m_curr_pid_is_valid = eLazyBoolYes;
- return m_curr_pid;
- }
- }
- }
-
- return LLDB_INVALID_PROCESS_ID;
-}
-bool
-GDBRemoteCommunicationClient::GetLaunchSuccess (std::string &error_str)
-{
- error_str.clear();
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qLaunchSuccess", strlen("qLaunchSuccess"), response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return true;
- if (response.GetChar() == 'E')
- {
- // A string the describes what failed when launching...
- error_str = response.GetStringRef().substr(1);
- }
- else
- {
- error_str.assign ("unknown error occurred launching process");
- }
- }
- else
- {
- error_str.assign ("timed out waiting for app to launch");
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
}
- return false;
+ }
+ return -1;
}
-int
-GDBRemoteCommunicationClient::SendArgumentsPacket (const ProcessLaunchInfo &launch_info)
-{
- // Since we don't get the send argv0 separate from the executable path, we need to
- // make sure to use the actual executable path found in the launch_info...
- std::vector<const char *> argv;
- FileSpec exe_file = launch_info.GetExecutableFile();
- std::string exe_path;
- const char *arg = NULL;
- const Args &launch_args = launch_info.GetArguments();
- if (exe_file)
- exe_path = exe_file.GetPath(false);
- else
- {
- arg = launch_args.GetArgumentAtIndex(0);
- if (arg)
- exe_path = arg;
- }
- if (!exe_path.empty())
- {
- argv.push_back(exe_path.c_str());
- for (uint32_t i=1; (arg = launch_args.GetArgumentAtIndex(i)) != NULL; ++i)
- {
- if (arg)
- argv.push_back(arg);
+int GDBRemoteCommunicationClient::SendEnvironmentPacket(
+ char const *name_equal_value) {
+ if (name_equal_value && name_equal_value[0]) {
+ StreamString packet;
+ bool send_hex_encoding = false;
+ for (const char *p = name_equal_value;
+ *p != '\0' && send_hex_encoding == false; ++p) {
+ if (isprint(*p)) {
+ switch (*p) {
+ case '$':
+ case '#':
+ case '*':
+ case '}':
+ send_hex_encoding = true;
+ break;
+ default:
+ break;
}
+ } else {
+ // We have non printable characters, lets hex encode this...
+ send_hex_encoding = true;
+ }
}
- if (!argv.empty())
- {
- StreamString packet;
- packet.PutChar('A');
- for (size_t i = 0, n = argv.size(); i < n; ++i)
- {
- arg = argv[i];
- const int arg_len = strlen(arg);
- if (i > 0)
- packet.PutChar(',');
- packet.Printf("%i,%i,", arg_len * 2, (int)i);
- packet.PutBytesAsRawHex8 (arg, arg_len);
- }
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
+ StringExtractorGDBRemote response;
+ if (send_hex_encoding) {
+ if (m_supports_QEnvironmentHexEncoded) {
+ packet.PutCString("QEnvironmentHexEncoded:");
+ packet.PutBytesAsRawHex8(name_equal_value, strlen(name_equal_value));
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ if (response.IsUnsupportedResponse())
+ m_supports_QEnvironmentHexEncoded = false;
}
- }
- return -1;
-}
+ }
-int
-GDBRemoteCommunicationClient::SendEnvironmentPacket (char const *name_equal_value)
-{
- if (name_equal_value && name_equal_value[0])
- {
- StreamString packet;
- bool send_hex_encoding = false;
- for (const char *p = name_equal_value; *p != '\0' && send_hex_encoding == false; ++p)
- {
- if (isprint(*p))
- {
- switch (*p)
- {
- case '$':
- case '#':
- case '*':
- case '}':
- send_hex_encoding = true;
- break;
- default:
- break;
- }
- }
- else
- {
- // We have non printable characters, lets hex encode this...
- send_hex_encoding = true;
- }
- }
-
- StringExtractorGDBRemote response;
- if (send_hex_encoding)
- {
- if (m_supports_QEnvironmentHexEncoded)
- {
- packet.PutCString("QEnvironmentHexEncoded:");
- packet.PutBytesAsRawHex8 (name_equal_value, strlen(name_equal_value));
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
- if (response.IsUnsupportedResponse())
- m_supports_QEnvironmentHexEncoded = false;
- }
- }
-
- }
- else if (m_supports_QEnvironment)
- {
- packet.Printf("QEnvironment:%s", name_equal_value);
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
- if (response.IsUnsupportedResponse())
- m_supports_QEnvironment = false;
- }
- }
+ } else if (m_supports_QEnvironment) {
+ packet.Printf("QEnvironment:%s", name_equal_value);
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ if (response.IsUnsupportedResponse())
+ m_supports_QEnvironment = false;
+ }
}
- return -1;
+ }
+ return -1;
}
-int
-GDBRemoteCommunicationClient::SendLaunchArchPacket (char const *arch)
-{
- if (arch && arch[0])
- {
- StreamString packet;
- packet.Printf("QLaunchArch:%s", arch);
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
- }
+int GDBRemoteCommunicationClient::SendLaunchArchPacket(char const *arch) {
+ if (arch && arch[0]) {
+ StreamString packet;
+ packet.Printf("QLaunchArch:%s", arch);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
}
- return -1;
+ }
+ return -1;
}
-int
-GDBRemoteCommunicationClient::SendLaunchEventDataPacket (char const *data, bool *was_supported)
-{
- if (data && *data != '\0')
- {
- StreamString packet;
- packet.Printf("QSetProcessEvent:%s", data);
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- {
- if (was_supported)
- *was_supported = true;
- return 0;
- }
- else if (response.IsUnsupportedResponse())
- {
- if (was_supported)
- *was_supported = false;
- return -1;
- }
- else
- {
- uint8_t error = response.GetError();
- if (was_supported)
- *was_supported = true;
- if (error)
- return error;
- }
- }
+int GDBRemoteCommunicationClient::SendLaunchEventDataPacket(
+ char const *data, bool *was_supported) {
+ if (data && *data != '\0') {
+ StreamString packet;
+ packet.Printf("QSetProcessEvent:%s", data);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ if (was_supported)
+ *was_supported = true;
+ return 0;
+ } else if (response.IsUnsupportedResponse()) {
+ if (was_supported)
+ *was_supported = false;
+ return -1;
+ } else {
+ uint8_t error = response.GetError();
+ if (was_supported)
+ *was_supported = true;
+ if (error)
+ return error;
+ }
}
- return -1;
+ }
+ return -1;
}
-bool
-GDBRemoteCommunicationClient::GetOSVersion (uint32_t &major,
- uint32_t &minor,
- uint32_t &update)
-{
- if (GetHostInfo ())
- {
- if (m_os_version_major != UINT32_MAX)
- {
- major = m_os_version_major;
- minor = m_os_version_minor;
- update = m_os_version_update;
- return true;
- }
+bool GDBRemoteCommunicationClient::GetOSVersion(uint32_t &major,
+ uint32_t &minor,
+ uint32_t &update) {
+ if (GetHostInfo()) {
+ if (m_os_version_major != UINT32_MAX) {
+ major = m_os_version_major;
+ minor = m_os_version_minor;
+ update = m_os_version_update;
+ return true;
}
- return false;
+ }
+ return false;
}
-bool
-GDBRemoteCommunicationClient::GetOSBuildString (std::string &s)
-{
- if (GetHostInfo ())
- {
- if (!m_os_build.empty())
- {
- s = m_os_build;
- return true;
- }
+bool GDBRemoteCommunicationClient::GetOSBuildString(std::string &s) {
+ if (GetHostInfo()) {
+ if (!m_os_build.empty()) {
+ s = m_os_build;
+ return true;
}
- s.clear();
- return false;
+ }
+ s.clear();
+ return false;
}
-
-bool
-GDBRemoteCommunicationClient::GetOSKernelDescription (std::string &s)
-{
- if (GetHostInfo ())
- {
- if (!m_os_kernel.empty())
- {
- s = m_os_kernel;
- return true;
- }
+bool GDBRemoteCommunicationClient::GetOSKernelDescription(std::string &s) {
+ if (GetHostInfo()) {
+ if (!m_os_kernel.empty()) {
+ s = m_os_kernel;
+ return true;
}
- s.clear();
- return false;
+ }
+ s.clear();
+ return false;
}
-bool
-GDBRemoteCommunicationClient::GetHostname (std::string &s)
-{
- if (GetHostInfo ())
- {
- if (!m_hostname.empty())
- {
- s = m_hostname;
- return true;
- }
+bool GDBRemoteCommunicationClient::GetHostname(std::string &s) {
+ if (GetHostInfo()) {
+ if (!m_hostname.empty()) {
+ s = m_hostname;
+ return true;
}
- s.clear();
- return false;
+ }
+ s.clear();
+ return false;
}
-ArchSpec
-GDBRemoteCommunicationClient::GetSystemArchitecture ()
-{
- if (GetHostInfo ())
- return m_host_arch;
- return ArchSpec();
+ArchSpec GDBRemoteCommunicationClient::GetSystemArchitecture() {
+ if (GetHostInfo())
+ return m_host_arch;
+ return ArchSpec();
}
const lldb_private::ArchSpec &
-GDBRemoteCommunicationClient::GetProcessArchitecture ()
-{
- if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
- GetCurrentProcessInfo ();
- return m_process_arch;
+GDBRemoteCommunicationClient::GetProcessArchitecture() {
+ if (m_qProcessInfo_is_valid == eLazyBoolCalculate)
+ GetCurrentProcessInfo();
+ return m_process_arch;
}
-bool
-GDBRemoteCommunicationClient::GetGDBServerVersion()
-{
- if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate)
- {
- m_gdb_server_name.clear();
- m_gdb_server_version = 0;
- m_qGDBServerVersion_is_valid = eLazyBoolNo;
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse ("qGDBServerVersion", response, false) == PacketResult::Success)
- {
- if (response.IsNormalResponse())
- {
- std::string name;
- std::string value;
- bool success = false;
- while (response.GetNameColonValue(name, value))
- {
- if (name.compare("name") == 0)
- {
- success = true;
- m_gdb_server_name.swap(value);
- }
- else if (name.compare("version") == 0)
- {
- size_t dot_pos = value.find('.');
- if (dot_pos != std::string::npos)
- value[dot_pos] = '\0';
- const uint32_t version = StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0);
- if (version != UINT32_MAX)
- {
- success = true;
- m_gdb_server_version = version;
- }
- }
- }
- if (success)
- m_qGDBServerVersion_is_valid = eLazyBoolYes;
- }
- }
- }
- return m_qGDBServerVersion_is_valid == eLazyBoolYes;
-}
+bool GDBRemoteCommunicationClient::GetGDBServerVersion() {
+ if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) {
+ m_gdb_server_name.clear();
+ m_gdb_server_version = 0;
+ m_qGDBServerVersion_is_valid = eLazyBoolNo;
-void
-GDBRemoteCommunicationClient::MaybeEnableCompression (std::vector<std::string> supported_compressions)
-{
- CompressionType avail_type = CompressionType::None;
- std::string avail_name;
-
-#if defined (HAVE_LIBCOMPRESSION)
- // libcompression is weak linked so test if compression_decode_buffer() is available
- if (compression_decode_buffer != NULL && avail_type == CompressionType::None)
- {
- for (auto compression : supported_compressions)
- {
- if (compression == "lzfse")
- {
- avail_type = CompressionType::LZFSE;
- avail_name = compression;
- break;
- }
- }
- }
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qGDBServerVersion", response, false) ==
+ PacketResult::Success) {
+ if (response.IsNormalResponse()) {
+ llvm::StringRef name, value;
+ bool success = false;
+ while (response.GetNameColonValue(name, value)) {
+ if (name.equals("name")) {
+ success = true;
+ m_gdb_server_name = value;
+ } else if (name.equals("version")) {
+ llvm::StringRef major, minor;
+ std::tie(major, minor) = value.split('.');
+ if (!major.getAsInteger(0, m_gdb_server_version))
+ success = true;
+ }
+ }
+ if (success)
+ m_qGDBServerVersion_is_valid = eLazyBoolYes;
+ }
+ }
+ }
+ return m_qGDBServerVersion_is_valid == eLazyBoolYes;
+}
+
+void GDBRemoteCommunicationClient::MaybeEnableCompression(
+ std::vector<std::string> supported_compressions) {
+ CompressionType avail_type = CompressionType::None;
+ std::string avail_name;
+
+#if defined(HAVE_LIBCOMPRESSION)
+ // libcompression is weak linked so test if compression_decode_buffer() is
+ // available
+ if (compression_decode_buffer != NULL &&
+ avail_type == CompressionType::None) {
+ for (auto compression : supported_compressions) {
+ if (compression == "lzfse") {
+ avail_type = CompressionType::LZFSE;
+ avail_name = compression;
+ break;
+ }
+ }
+ }
#endif
-#if defined (HAVE_LIBCOMPRESSION)
- // libcompression is weak linked so test if compression_decode_buffer() is available
- if (compression_decode_buffer != NULL && avail_type == CompressionType::None)
- {
- for (auto compression : supported_compressions)
- {
- if (compression == "zlib-deflate")
- {
- avail_type = CompressionType::ZlibDeflate;
- avail_name = compression;
- break;
- }
- }
- }
+#if defined(HAVE_LIBCOMPRESSION)
+ // libcompression is weak linked so test if compression_decode_buffer() is
+ // available
+ if (compression_decode_buffer != NULL &&
+ avail_type == CompressionType::None) {
+ for (auto compression : supported_compressions) {
+ if (compression == "zlib-deflate") {
+ avail_type = CompressionType::ZlibDeflate;
+ avail_name = compression;
+ break;
+ }
+ }
+ }
#endif
-#if defined (HAVE_LIBZ)
- if (avail_type == CompressionType::None)
- {
- for (auto compression : supported_compressions)
- {
- if (compression == "zlib-deflate")
- {
- avail_type = CompressionType::ZlibDeflate;
- avail_name = compression;
- break;
- }
- }
+#if defined(HAVE_LIBZ)
+ if (avail_type == CompressionType::None) {
+ for (auto compression : supported_compressions) {
+ if (compression == "zlib-deflate") {
+ avail_type = CompressionType::ZlibDeflate;
+ avail_name = compression;
+ break;
+ }
}
+ }
#endif
-#if defined (HAVE_LIBCOMPRESSION)
- // libcompression is weak linked so test if compression_decode_buffer() is available
- if (compression_decode_buffer != NULL && avail_type == CompressionType::None)
- {
- for (auto compression : supported_compressions)
- {
- if (compression == "lz4")
- {
- avail_type = CompressionType::LZ4;
- avail_name = compression;
- break;
- }
- }
- }
+#if defined(HAVE_LIBCOMPRESSION)
+ // libcompression is weak linked so test if compression_decode_buffer() is
+ // available
+ if (compression_decode_buffer != NULL &&
+ avail_type == CompressionType::None) {
+ for (auto compression : supported_compressions) {
+ if (compression == "lz4") {
+ avail_type = CompressionType::LZ4;
+ avail_name = compression;
+ break;
+ }
+ }
+ }
#endif
-#if defined (HAVE_LIBCOMPRESSION)
- // libcompression is weak linked so test if compression_decode_buffer() is available
- if (compression_decode_buffer != NULL && avail_type == CompressionType::None)
- {
- for (auto compression : supported_compressions)
- {
- if (compression == "lzma")
- {
- avail_type = CompressionType::LZMA;
- avail_name = compression;
- break;
- }
- }
- }
+#if defined(HAVE_LIBCOMPRESSION)
+ // libcompression is weak linked so test if compression_decode_buffer() is
+ // available
+ if (compression_decode_buffer != NULL &&
+ avail_type == CompressionType::None) {
+ for (auto compression : supported_compressions) {
+ if (compression == "lzma") {
+ avail_type = CompressionType::LZMA;
+ avail_name = compression;
+ break;
+ }
+ }
+ }
#endif
- if (avail_type != CompressionType::None)
- {
- StringExtractorGDBRemote response;
- std::string packet = "QEnableCompression:type:" + avail_name + ";";
- if (SendPacketAndWaitForResponse (packet.c_str(), response, false) != PacketResult::Success)
- return;
-
- if (response.IsOKResponse())
- {
- m_compression_type = avail_type;
- }
- }
-}
+ if (avail_type != CompressionType::None) {
+ StringExtractorGDBRemote response;
+ std::string packet = "QEnableCompression:type:" + avail_name + ";";
+ if (SendPacketAndWaitForResponse(packet, response, false) !=
+ PacketResult::Success)
+ return;
-const char *
-GDBRemoteCommunicationClient::GetGDBServerProgramName()
-{
- if (GetGDBServerVersion())
- {
- if (!m_gdb_server_name.empty())
- return m_gdb_server_name.c_str();
+ if (response.IsOKResponse()) {
+ m_compression_type = avail_type;
}
- return NULL;
+ }
}
-uint32_t
-GDBRemoteCommunicationClient::GetGDBServerProgramVersion()
-{
- if (GetGDBServerVersion())
- return m_gdb_server_version;
- return 0;
+const char *GDBRemoteCommunicationClient::GetGDBServerProgramName() {
+ if (GetGDBServerVersion()) {
+ if (!m_gdb_server_name.empty())
+ return m_gdb_server_name.c_str();
+ }
+ return NULL;
}
-bool
-GDBRemoteCommunicationClient::GetDefaultThreadId (lldb::tid_t &tid)
-{
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qC",response,false) != PacketResult::Success)
- return false;
-
- if (!response.IsNormalResponse())
- return false;
-
- if (response.GetChar() == 'Q' && response.GetChar() == 'C')
- tid = response.GetHexMaxU32(true, -1);
-
- return true;
+uint32_t GDBRemoteCommunicationClient::GetGDBServerProgramVersion() {
+ if (GetGDBServerVersion())
+ return m_gdb_server_version;
+ return 0;
}
-bool
-GDBRemoteCommunicationClient::GetHostInfo (bool force)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS));
-
- if (force || m_qHostInfo_is_valid == eLazyBoolCalculate)
- {
- m_qHostInfo_is_valid = eLazyBoolNo;
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse ("qHostInfo", response, false) == PacketResult::Success)
- {
- if (response.IsNormalResponse())
- {
- std::string name;
- std::string value;
- uint32_t cpu = LLDB_INVALID_CPUTYPE;
- uint32_t sub = 0;
- std::string arch_name;
- std::string os_name;
- std::string vendor_name;
- std::string triple;
- std::string distribution_id;
- uint32_t pointer_byte_size = 0;
- StringExtractor extractor;
- ByteOrder byte_order = eByteOrderInvalid;
- uint32_t num_keys_decoded = 0;
- while (response.GetNameColonValue(name, value))
- {
- if (name.compare("cputype") == 0)
- {
- // exception type in big endian hex
- cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0);
- if (cpu != LLDB_INVALID_CPUTYPE)
- ++num_keys_decoded;
- }
- else if (name.compare("cpusubtype") == 0)
- {
- // exception count in big endian hex
- sub = StringConvert::ToUInt32 (value.c_str(), 0, 0);
- if (sub != 0)
- ++num_keys_decoded;
- }
- else if (name.compare("arch") == 0)
- {
- arch_name.swap (value);
- ++num_keys_decoded;
- }
- else if (name.compare("triple") == 0)
- {
- extractor.GetStringRef ().swap (value);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (triple);
- ++num_keys_decoded;
- }
- else if (name.compare ("distribution_id") == 0)
- {
- extractor.GetStringRef ().swap (value);
- extractor.SetFilePos (0);
- extractor.GetHexByteString (distribution_id);
- ++num_keys_decoded;
- }
- else if (name.compare("os_build") == 0)
- {
- extractor.GetStringRef().swap(value);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (m_os_build);
- ++num_keys_decoded;
- }
- else if (name.compare("hostname") == 0)
- {
- extractor.GetStringRef().swap(value);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (m_hostname);
- ++num_keys_decoded;
- }
- else if (name.compare("os_kernel") == 0)
- {
- extractor.GetStringRef().swap(value);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (m_os_kernel);
- ++num_keys_decoded;
- }
- else if (name.compare("ostype") == 0)
- {
- os_name.swap (value);
- ++num_keys_decoded;
- }
- else if (name.compare("vendor") == 0)
- {
- vendor_name.swap(value);
- ++num_keys_decoded;
- }
- else if (name.compare("endian") == 0)
- {
- ++num_keys_decoded;
- if (value.compare("little") == 0)
- byte_order = eByteOrderLittle;
- else if (value.compare("big") == 0)
- byte_order = eByteOrderBig;
- else if (value.compare("pdp") == 0)
- byte_order = eByteOrderPDP;
- else
- --num_keys_decoded;
- }
- else if (name.compare("ptrsize") == 0)
- {
- pointer_byte_size = StringConvert::ToUInt32 (value.c_str(), 0, 0);
- if (pointer_byte_size != 0)
- ++num_keys_decoded;
- }
- else if ((name.compare("os_version") == 0) ||
- (name.compare("version") == 0)) // Older debugserver binaries used the "version" key instead of "os_version"...
- {
- Args::StringToVersion (value.c_str(),
- m_os_version_major,
- m_os_version_minor,
- m_os_version_update);
- if (m_os_version_major != UINT32_MAX)
- ++num_keys_decoded;
- }
- else if (name.compare("watchpoint_exceptions_received") == 0)
- {
- ++num_keys_decoded;
- if (strcmp(value.c_str(),"before") == 0)
- m_watchpoints_trigger_after_instruction = eLazyBoolNo;
- else if (strcmp(value.c_str(),"after") == 0)
- m_watchpoints_trigger_after_instruction = eLazyBoolYes;
- else
- --num_keys_decoded;
- }
- else if (name.compare("default_packet_timeout") == 0)
- {
- m_default_packet_timeout = StringConvert::ToUInt32(value.c_str(), 0);
- if (m_default_packet_timeout > 0)
- {
- SetPacketTimeout(m_default_packet_timeout);
- ++num_keys_decoded;
- }
- }
+bool GDBRemoteCommunicationClient::GetDefaultThreadId(lldb::tid_t &tid) {
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qC", response, false) !=
+ PacketResult::Success)
+ return false;
- }
-
- if (num_keys_decoded > 0)
- m_qHostInfo_is_valid = eLazyBoolYes;
-
- if (triple.empty())
- {
- if (arch_name.empty())
- {
- if (cpu != LLDB_INVALID_CPUTYPE)
- {
- m_host_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
- if (pointer_byte_size)
- {
- assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
- }
- if (byte_order != eByteOrderInvalid)
- {
- assert (byte_order == m_host_arch.GetByteOrder());
- }
-
- if (!vendor_name.empty())
- m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
- if (!os_name.empty())
- m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name));
-
- }
- }
- else
- {
- std::string triple;
- triple += arch_name;
- if (!vendor_name.empty() || !os_name.empty())
- {
- triple += '-';
- if (vendor_name.empty())
- triple += "unknown";
- else
- triple += vendor_name;
- triple += '-';
- if (os_name.empty())
- triple += "unknown";
- else
- triple += os_name;
- }
- m_host_arch.SetTriple (triple.c_str());
-
- llvm::Triple &host_triple = m_host_arch.GetTriple();
- if (host_triple.getVendor() == llvm::Triple::Apple && host_triple.getOS() == llvm::Triple::Darwin)
- {
- switch (m_host_arch.GetMachine())
- {
- case llvm::Triple::aarch64:
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- host_triple.setOS(llvm::Triple::IOS);
- break;
- default:
- host_triple.setOS(llvm::Triple::MacOSX);
- break;
- }
- }
- if (pointer_byte_size)
- {
- assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
- }
- if (byte_order != eByteOrderInvalid)
- {
- assert (byte_order == m_host_arch.GetByteOrder());
- }
-
- }
- }
- else
- {
- m_host_arch.SetTriple (triple.c_str());
- if (pointer_byte_size)
- {
- assert (pointer_byte_size == m_host_arch.GetAddressByteSize());
- }
- if (byte_order != eByteOrderInvalid)
- {
- assert (byte_order == m_host_arch.GetByteOrder());
- }
+ if (!response.IsNormalResponse())
+ return false;
- if (log)
- log->Printf ("GDBRemoteCommunicationClient::%s parsed host architecture as %s, triple as %s from triple text %s", __FUNCTION__, m_host_arch.GetArchitectureName () ? m_host_arch.GetArchitectureName () : "<null-arch-name>", m_host_arch.GetTriple ().getTriple ().c_str(), triple.c_str ());
- }
- if (!distribution_id.empty ())
- m_host_arch.SetDistributionId (distribution_id.c_str ());
- }
- }
- }
- return m_qHostInfo_is_valid == eLazyBoolYes;
-}
+ if (response.GetChar() == 'Q' && response.GetChar() == 'C')
+ tid = response.GetHexMaxU32(true, -1);
-int
-GDBRemoteCommunicationClient::SendAttach
-(
- lldb::pid_t pid,
- StringExtractorGDBRemote& response
-)
-{
- if (pid != LLDB_INVALID_PROCESS_ID)
- {
- char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, pid);
- assert (packet_len < (int)sizeof(packet));
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsErrorResponse())
- return response.GetError();
- return 0;
- }
- }
- return -1;
+ return true;
}
-int
-GDBRemoteCommunicationClient::SendStdinNotification (const char* data, size_t data_len)
-{
- StreamString packet;
- packet.PutCString("I");
- packet.PutBytesAsRawHex8(data, data_len);
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- return 0;
- }
- return response.GetError();
+bool GDBRemoteCommunicationClient::GetHostInfo(bool force) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS));
+ if (force || m_qHostInfo_is_valid == eLazyBoolCalculate) {
+ m_qHostInfo_is_valid = eLazyBoolNo;
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qHostInfo", response, false) ==
+ PacketResult::Success) {
+ if (response.IsNormalResponse()) {
+ llvm::StringRef name;
+ llvm::StringRef value;
+ uint32_t cpu = LLDB_INVALID_CPUTYPE;
+ uint32_t sub = 0;
+ std::string arch_name;
+ std::string os_name;
+ std::string vendor_name;
+ std::string triple;
+ std::string distribution_id;
+ uint32_t pointer_byte_size = 0;
+ ByteOrder byte_order = eByteOrderInvalid;
+ uint32_t num_keys_decoded = 0;
+ while (response.GetNameColonValue(name, value)) {
+ if (name.equals("cputype")) {
+ // exception type in big endian hex
+ if (!value.getAsInteger(0, cpu))
+ ++num_keys_decoded;
+ } else if (name.equals("cpusubtype")) {
+ // exception count in big endian hex
+ if (!value.getAsInteger(0, sub))
+ ++num_keys_decoded;
+ } else if (name.equals("arch")) {
+ arch_name = value;
+ ++num_keys_decoded;
+ } else if (name.equals("triple")) {
+ StringExtractor extractor(value);
+ extractor.GetHexByteString(triple);
+ ++num_keys_decoded;
+ } else if (name.equals("distribution_id")) {
+ StringExtractor extractor(value);
+ extractor.GetHexByteString(distribution_id);
+ ++num_keys_decoded;
+ } else if (name.equals("os_build")) {
+ StringExtractor extractor(value);
+ extractor.GetHexByteString(m_os_build);
+ ++num_keys_decoded;
+ } else if (name.equals("hostname")) {
+ StringExtractor extractor(value);
+ extractor.GetHexByteString(m_hostname);
+ ++num_keys_decoded;
+ } else if (name.equals("os_kernel")) {
+ StringExtractor extractor(value);
+ extractor.GetHexByteString(m_os_kernel);
+ ++num_keys_decoded;
+ } else if (name.equals("ostype")) {
+ os_name = value;
+ ++num_keys_decoded;
+ } else if (name.equals("vendor")) {
+ vendor_name = value;
+ ++num_keys_decoded;
+ } else if (name.equals("endian")) {
+ byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
+ .Case("little", eByteOrderLittle)
+ .Case("big", eByteOrderBig)
+ .Case("pdp", eByteOrderPDP)
+ .Default(eByteOrderInvalid);
+ if (byte_order != eByteOrderInvalid)
+ ++num_keys_decoded;
+ } else if (name.equals("ptrsize")) {
+ if (!value.getAsInteger(0, pointer_byte_size))
+ ++num_keys_decoded;
+ } else if (name.equals("os_version") ||
+ name.equals(
+ "version")) // Older debugserver binaries used the
+ // "version" key instead of
+ // "os_version"...
+ {
+ Args::StringToVersion(value, m_os_version_major, m_os_version_minor,
+ m_os_version_update);
+ if (m_os_version_major != UINT32_MAX)
+ ++num_keys_decoded;
+ } else if (name.equals("watchpoint_exceptions_received")) {
+ m_watchpoints_trigger_after_instruction =
+ llvm::StringSwitch<LazyBool>(value)
+ .Case("before", eLazyBoolNo)
+ .Case("after", eLazyBoolYes)
+ .Default(eLazyBoolCalculate);
+ if (m_watchpoints_trigger_after_instruction != eLazyBoolCalculate)
+ ++num_keys_decoded;
+ } else if (name.equals("default_packet_timeout")) {
+ uint32_t timeout_seconds;
+ if (!value.getAsInteger(0, timeout_seconds)) {
+ m_default_packet_timeout = seconds(timeout_seconds);
+ SetPacketTimeout(m_default_packet_timeout);
+ ++num_keys_decoded;
+ }
+ }
+ }
+
+ if (num_keys_decoded > 0)
+ m_qHostInfo_is_valid = eLazyBoolYes;
+
+ if (triple.empty()) {
+ if (arch_name.empty()) {
+ if (cpu != LLDB_INVALID_CPUTYPE) {
+ m_host_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
+ if (pointer_byte_size) {
+ assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
+ }
+ if (byte_order != eByteOrderInvalid) {
+ assert(byte_order == m_host_arch.GetByteOrder());
+ }
+
+ if (!vendor_name.empty())
+ m_host_arch.GetTriple().setVendorName(
+ llvm::StringRef(vendor_name));
+ if (!os_name.empty())
+ m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name));
+ }
+ } else {
+ std::string triple;
+ triple += arch_name;
+ if (!vendor_name.empty() || !os_name.empty()) {
+ triple += '-';
+ if (vendor_name.empty())
+ triple += "unknown";
+ else
+ triple += vendor_name;
+ triple += '-';
+ if (os_name.empty())
+ triple += "unknown";
+ else
+ triple += os_name;
+ }
+ m_host_arch.SetTriple(triple.c_str());
+
+ llvm::Triple &host_triple = m_host_arch.GetTriple();
+ if (host_triple.getVendor() == llvm::Triple::Apple &&
+ host_triple.getOS() == llvm::Triple::Darwin) {
+ switch (m_host_arch.GetMachine()) {
+ case llvm::Triple::aarch64:
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ host_triple.setOS(llvm::Triple::IOS);
+ break;
+ default:
+ host_triple.setOS(llvm::Triple::MacOSX);
+ break;
+ }
+ }
+ if (pointer_byte_size) {
+ assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
+ }
+ if (byte_order != eByteOrderInvalid) {
+ assert(byte_order == m_host_arch.GetByteOrder());
+ }
+ }
+ } else {
+ m_host_arch.SetTriple(triple.c_str());
+ if (pointer_byte_size) {
+ assert(pointer_byte_size == m_host_arch.GetAddressByteSize());
+ }
+ if (byte_order != eByteOrderInvalid) {
+ assert(byte_order == m_host_arch.GetByteOrder());
+ }
+
+ if (log)
+ log->Printf("GDBRemoteCommunicationClient::%s parsed host "
+ "architecture as %s, triple as %s from triple text %s",
+ __FUNCTION__, m_host_arch.GetArchitectureName()
+ ? m_host_arch.GetArchitectureName()
+ : "<null-arch-name>",
+ m_host_arch.GetTriple().getTriple().c_str(),
+ triple.c_str());
+ }
+ if (!distribution_id.empty())
+ m_host_arch.SetDistributionId(distribution_id.c_str());
+ }
+ }
+ }
+ return m_qHostInfo_is_valid == eLazyBoolYes;
+}
+
+int GDBRemoteCommunicationClient::SendAttach(
+ lldb::pid_t pid, StringExtractorGDBRemote &response) {
+ if (pid != LLDB_INVALID_PROCESS_ID) {
+ char packet[64];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, pid);
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ assert(packet_len < (int)sizeof(packet));
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsErrorResponse())
+ return response.GetError();
+ return 0;
+ }
+ }
+ return -1;
+}
+
+int GDBRemoteCommunicationClient::SendStdinNotification(const char *data,
+ size_t data_len) {
+ StreamString packet;
+ packet.PutCString("I");
+ packet.PutBytesAsRawHex8(data, data_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ return 0;
+ }
+ return response.GetError();
}
const lldb_private::ArchSpec &
-GDBRemoteCommunicationClient::GetHostArchitecture ()
-{
- if (m_qHostInfo_is_valid == eLazyBoolCalculate)
- GetHostInfo ();
- return m_host_arch;
+GDBRemoteCommunicationClient::GetHostArchitecture() {
+ if (m_qHostInfo_is_valid == eLazyBoolCalculate)
+ GetHostInfo();
+ return m_host_arch;
}
-uint32_t
-GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout ()
-{
- if (m_qHostInfo_is_valid == eLazyBoolCalculate)
- GetHostInfo ();
- return m_default_packet_timeout;
+seconds GDBRemoteCommunicationClient::GetHostDefaultPacketTimeout() {
+ if (m_qHostInfo_is_valid == eLazyBoolCalculate)
+ GetHostInfo();
+ return m_default_packet_timeout;
}
-addr_t
-GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions)
-{
- if (m_supports_alloc_dealloc_memory != eLazyBoolNo)
- {
- m_supports_alloc_dealloc_memory = eLazyBoolYes;
- char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s",
- (uint64_t)size,
- permissions & lldb::ePermissionsReadable ? "r" : "",
- permissions & lldb::ePermissionsWritable ? "w" : "",
- permissions & lldb::ePermissionsExecutable ? "x" : "");
- assert (packet_len < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsUnsupportedResponse())
- m_supports_alloc_dealloc_memory = eLazyBoolNo;
- else if (!response.IsErrorResponse())
- return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
- }
- else
- {
- m_supports_alloc_dealloc_memory = eLazyBoolNo;
- }
- }
- return LLDB_INVALID_ADDRESS;
+addr_t GDBRemoteCommunicationClient::AllocateMemory(size_t size,
+ uint32_t permissions) {
+ if (m_supports_alloc_dealloc_memory != eLazyBoolNo) {
+ m_supports_alloc_dealloc_memory = eLazyBoolYes;
+ char packet[64];
+ const int packet_len = ::snprintf(
+ packet, sizeof(packet), "_M%" PRIx64 ",%s%s%s", (uint64_t)size,
+ permissions & lldb::ePermissionsReadable ? "r" : "",
+ permissions & lldb::ePermissionsWritable ? "w" : "",
+ permissions & lldb::ePermissionsExecutable ? "x" : "");
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsUnsupportedResponse())
+ m_supports_alloc_dealloc_memory = eLazyBoolNo;
+ else if (!response.IsErrorResponse())
+ return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
+ } else {
+ m_supports_alloc_dealloc_memory = eLazyBoolNo;
+ }
+ }
+ return LLDB_INVALID_ADDRESS;
+}
+
+bool GDBRemoteCommunicationClient::DeallocateMemory(addr_t addr) {
+ if (m_supports_alloc_dealloc_memory != eLazyBoolNo) {
+ m_supports_alloc_dealloc_memory = eLazyBoolYes;
+ char packet[64];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr);
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsUnsupportedResponse())
+ m_supports_alloc_dealloc_memory = eLazyBoolNo;
+ else if (response.IsOKResponse())
+ return true;
+ } else {
+ m_supports_alloc_dealloc_memory = eLazyBoolNo;
+ }
+ }
+ return false;
+}
+
+Error GDBRemoteCommunicationClient::Detach(bool keep_stopped) {
+ Error error;
+
+ if (keep_stopped) {
+ if (m_supports_detach_stay_stopped == eLazyBoolCalculate) {
+ char packet[64];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success &&
+ response.IsOKResponse()) {
+ m_supports_detach_stay_stopped = eLazyBoolYes;
+ } else {
+ m_supports_detach_stay_stopped = eLazyBoolNo;
+ }
+ }
+
+ if (m_supports_detach_stay_stopped == eLazyBoolNo) {
+ error.SetErrorString("Stays stopped not supported by this target.");
+ return error;
+ } else {
+ StringExtractorGDBRemote response;
+ PacketResult packet_result =
+ SendPacketAndWaitForResponse("D1", response, false);
+ if (packet_result != PacketResult::Success)
+ error.SetErrorString("Sending extended disconnect packet failed.");
+ }
+ } else {
+ StringExtractorGDBRemote response;
+ PacketResult packet_result =
+ SendPacketAndWaitForResponse("D", response, false);
+ if (packet_result != PacketResult::Success)
+ error.SetErrorString("Sending disconnect packet failed.");
+ }
+ return error;
}
-bool
-GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr)
-{
- if (m_supports_alloc_dealloc_memory != eLazyBoolNo)
- {
- m_supports_alloc_dealloc_memory = eLazyBoolYes;
- char packet[64];
- const int packet_len = ::snprintf(packet, sizeof(packet), "_m%" PRIx64, (uint64_t)addr);
- assert (packet_len < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsUnsupportedResponse())
- m_supports_alloc_dealloc_memory = eLazyBoolNo;
- else if (response.IsOKResponse())
- return true;
- }
- else
- {
- m_supports_alloc_dealloc_memory = eLazyBoolNo;
- }
- }
- return false;
-}
+Error GDBRemoteCommunicationClient::GetMemoryRegionInfo(
+ lldb::addr_t addr, lldb_private::MemoryRegionInfo &region_info) {
+ Error error;
+ region_info.Clear();
-Error
-GDBRemoteCommunicationClient::Detach (bool keep_stopped)
-{
- Error error;
-
- if (keep_stopped)
- {
- if (m_supports_detach_stay_stopped == eLazyBoolCalculate)
- {
- char packet[64];
- const int packet_len = ::snprintf(packet, sizeof(packet), "qSupportsDetachAndStayStopped:");
- assert (packet_len < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success
- && response.IsOKResponse())
- {
- m_supports_detach_stay_stopped = eLazyBoolYes;
- }
+ if (m_supports_memory_region_info != eLazyBoolNo) {
+ m_supports_memory_region_info = eLazyBoolYes;
+ char packet[64];
+ const int packet_len = ::snprintf(
+ packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr);
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ llvm::StringRef name;
+ llvm::StringRef value;
+ addr_t addr_value = LLDB_INVALID_ADDRESS;
+ bool success = true;
+ bool saw_permissions = false;
+ while (success && response.GetNameColonValue(name, value)) {
+ if (name.equals("start")) {
+ if (!value.getAsInteger(16, addr_value))
+ region_info.GetRange().SetRangeBase(addr_value);
+ } else if (name.equals("size")) {
+ if (!value.getAsInteger(16, addr_value))
+ region_info.GetRange().SetByteSize(addr_value);
+ } else if (name.equals("permissions") &&
+ region_info.GetRange().IsValid()) {
+ saw_permissions = true;
+ if (region_info.GetRange().Contains(addr)) {
+ if (value.find('r') != llvm::StringRef::npos)
+ region_info.SetReadable(MemoryRegionInfo::eYes);
else
- {
- m_supports_detach_stay_stopped = eLazyBoolNo;
- }
- }
+ region_info.SetReadable(MemoryRegionInfo::eNo);
- if (m_supports_detach_stay_stopped == eLazyBoolNo)
- {
- error.SetErrorString("Stays stopped not supported by this target.");
- return error;
- }
- else
- {
- StringExtractorGDBRemote response;
- PacketResult packet_result = SendPacketAndWaitForResponse ("D1", 2, response, false);
- if (packet_result != PacketResult::Success)
- error.SetErrorString ("Sending extended disconnect packet failed.");
- }
- }
- else
- {
- StringExtractorGDBRemote response;
- PacketResult packet_result = SendPacketAndWaitForResponse ("D", 1, response, false);
- if (packet_result != PacketResult::Success)
- error.SetErrorString ("Sending disconnect packet failed.");
- }
- return error;
-}
+ if (value.find('w') != llvm::StringRef::npos)
+ region_info.SetWritable(MemoryRegionInfo::eYes);
+ else
+ region_info.SetWritable(MemoryRegionInfo::eNo);
-Error
-GDBRemoteCommunicationClient::GetMemoryRegionInfo (lldb::addr_t addr,
- lldb_private::MemoryRegionInfo &region_info)
-{
- Error error;
+ if (value.find('x') != llvm::StringRef::npos)
+ region_info.SetExecutable(MemoryRegionInfo::eYes);
+ else
+ region_info.SetExecutable(MemoryRegionInfo::eNo);
+
+ region_info.SetMapped(MemoryRegionInfo::eYes);
+ } else {
+ // The reported region does not contain this address -- we're
+ // looking at an unmapped page
+ region_info.SetReadable(MemoryRegionInfo::eNo);
+ region_info.SetWritable(MemoryRegionInfo::eNo);
+ region_info.SetExecutable(MemoryRegionInfo::eNo);
+ region_info.SetMapped(MemoryRegionInfo::eNo);
+ }
+ } else if (name.equals("name")) {
+ StringExtractorGDBRemote name_extractor(value);
+ std::string name;
+ name_extractor.GetHexByteString(name);
+ region_info.SetName(name.c_str());
+ } else if (name.equals("error")) {
+ StringExtractorGDBRemote error_extractor(value);
+ std::string error_string;
+ // Now convert the HEX bytes into a string value
+ error_extractor.GetHexByteString(error_string);
+ error.SetErrorString(error_string.c_str());
+ }
+ }
+
+ // We got a valid address range back but no permissions -- which means
+ // this is an unmapped page
+ if (region_info.GetRange().IsValid() && saw_permissions == false) {
+ region_info.SetReadable(MemoryRegionInfo::eNo);
+ region_info.SetWritable(MemoryRegionInfo::eNo);
+ region_info.SetExecutable(MemoryRegionInfo::eNo);
+ region_info.SetMapped(MemoryRegionInfo::eNo);
+ }
+ } else {
+ m_supports_memory_region_info = eLazyBoolNo;
+ }
+ }
+
+ if (m_supports_memory_region_info == eLazyBoolNo) {
+ error.SetErrorString("qMemoryRegionInfo is not supported");
+ }
+ if (error.Fail())
region_info.Clear();
-
- if (m_supports_memory_region_info != eLazyBoolNo)
- {
- m_supports_memory_region_info = eLazyBoolYes;
- char packet[64];
- const int packet_len = ::snprintf(packet, sizeof(packet), "qMemoryRegionInfo:%" PRIx64, (uint64_t)addr);
- assert (packet_len < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
- {
- std::string name;
- std::string value;
- addr_t addr_value;
- bool success = true;
- bool saw_permissions = false;
- while (success && response.GetNameColonValue(name, value))
- {
- if (name.compare ("start") == 0)
- {
- addr_value = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16, &success);
- if (success)
- region_info.GetRange().SetRangeBase(addr_value);
- }
- else if (name.compare ("size") == 0)
- {
- addr_value = StringConvert::ToUInt64(value.c_str(), 0, 16, &success);
- if (success)
- region_info.GetRange().SetByteSize (addr_value);
- }
- else if (name.compare ("permissions") == 0 && region_info.GetRange().IsValid())
- {
- saw_permissions = true;
- if (region_info.GetRange().Contains (addr))
- {
- if (value.find('r') != std::string::npos)
- region_info.SetReadable (MemoryRegionInfo::eYes);
- else
- region_info.SetReadable (MemoryRegionInfo::eNo);
-
- if (value.find('w') != std::string::npos)
- region_info.SetWritable (MemoryRegionInfo::eYes);
- else
- region_info.SetWritable (MemoryRegionInfo::eNo);
-
- if (value.find('x') != std::string::npos)
- region_info.SetExecutable (MemoryRegionInfo::eYes);
- else
- region_info.SetExecutable (MemoryRegionInfo::eNo);
-
- region_info.SetMapped(MemoryRegionInfo::eYes);
- }
- else
- {
- // The reported region does not contain this address -- we're looking at an unmapped page
- region_info.SetReadable (MemoryRegionInfo::eNo);
- region_info.SetWritable (MemoryRegionInfo::eNo);
- region_info.SetExecutable (MemoryRegionInfo::eNo);
- region_info.SetMapped(MemoryRegionInfo::eNo);
- }
- }
- else if (name.compare ("error") == 0)
- {
- StringExtractorGDBRemote name_extractor;
- // Swap "value" over into "name_extractor"
- name_extractor.GetStringRef().swap(value);
- // Now convert the HEX bytes into a string value
- name_extractor.GetHexByteString (value);
- error.SetErrorString(value.c_str());
- }
- }
-
- // We got a valid address range back but no permissions -- which means this is an unmapped page
- if (region_info.GetRange().IsValid() && saw_permissions == false)
- {
- region_info.SetReadable (MemoryRegionInfo::eNo);
- region_info.SetWritable (MemoryRegionInfo::eNo);
- region_info.SetExecutable (MemoryRegionInfo::eNo);
- region_info.SetMapped(MemoryRegionInfo::eNo);
- }
- }
- else
- {
- m_supports_memory_region_info = eLazyBoolNo;
- }
- }
-
- if (m_supports_memory_region_info == eLazyBoolNo)
- {
- error.SetErrorString("qMemoryRegionInfo is not supported");
- }
- if (error.Fail())
- region_info.Clear();
- return error;
-
+ return error;
}
-Error
-GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num)
-{
- Error error;
+Error GDBRemoteCommunicationClient::GetWatchpointSupportInfo(uint32_t &num) {
+ Error error;
- if (m_supports_watchpoint_support_info == eLazyBoolYes)
- {
- num = m_num_supported_hardware_watchpoints;
- return error;
- }
+ if (m_supports_watchpoint_support_info == eLazyBoolYes) {
+ num = m_num_supported_hardware_watchpoints;
+ return error;
+ }
- // Set num to 0 first.
- num = 0;
- if (m_supports_watchpoint_support_info != eLazyBoolNo)
- {
- char packet[64];
- const int packet_len = ::snprintf(packet, sizeof(packet), "qWatchpointSupportInfo:");
- assert (packet_len < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
- {
- m_supports_watchpoint_support_info = eLazyBoolYes;
- std::string name;
- std::string value;
- while (response.GetNameColonValue(name, value))
- {
- if (name.compare ("num") == 0)
- {
- num = StringConvert::ToUInt32(value.c_str(), 0, 0);
- m_num_supported_hardware_watchpoints = num;
- }
- }
- }
- else
- {
- m_supports_watchpoint_support_info = eLazyBoolNo;
+ // Set num to 0 first.
+ num = 0;
+ if (m_supports_watchpoint_support_info != eLazyBoolNo) {
+ char packet[64];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "qWatchpointSupportInfo:");
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ m_supports_watchpoint_support_info = eLazyBoolYes;
+ llvm::StringRef name;
+ llvm::StringRef value;
+ while (response.GetNameColonValue(name, value)) {
+ if (name.equals("num")) {
+ value.getAsInteger(0, m_num_supported_hardware_watchpoints);
+ num = m_num_supported_hardware_watchpoints;
}
+ }
+ } else {
+ m_supports_watchpoint_support_info = eLazyBoolNo;
}
+ }
- if (m_supports_watchpoint_support_info == eLazyBoolNo)
- {
- error.SetErrorString("qWatchpointSupportInfo is not supported");
- }
- return error;
-
+ if (m_supports_watchpoint_support_info == eLazyBoolNo) {
+ error.SetErrorString("qWatchpointSupportInfo is not supported");
+ }
+ return error;
}
-lldb_private::Error
-GDBRemoteCommunicationClient::GetWatchpointSupportInfo (uint32_t &num, bool& after, const ArchSpec &arch)
-{
- Error error(GetWatchpointSupportInfo(num));
- if (error.Success())
- error = GetWatchpointsTriggerAfterInstruction(after, arch);
- return error;
+lldb_private::Error GDBRemoteCommunicationClient::GetWatchpointSupportInfo(
+ uint32_t &num, bool &after, const ArchSpec &arch) {
+ Error error(GetWatchpointSupportInfo(num));
+ if (error.Success())
+ error = GetWatchpointsTriggerAfterInstruction(after, arch);
+ return error;
}
lldb_private::Error
-GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction (bool &after, const ArchSpec &arch)
-{
- Error error;
- llvm::Triple::ArchType atype = arch.GetMachine();
-
- // we assume watchpoints will happen after running the relevant opcode
- // and we only want to override this behavior if we have explicitly
- // received a qHostInfo telling us otherwise
- if (m_qHostInfo_is_valid != eLazyBoolYes)
- {
- // On targets like MIPS, watchpoint exceptions are always generated
- // before the instruction is executed. The connected target may not
- // support qHostInfo or qWatchpointSupportInfo packets.
- if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel
- || atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el)
- after = false;
- else
- after = true;
- }
+GDBRemoteCommunicationClient::GetWatchpointsTriggerAfterInstruction(
+ bool &after, const ArchSpec &arch) {
+ Error error;
+ llvm::Triple::ArchType atype = arch.GetMachine();
+
+ // we assume watchpoints will happen after running the relevant opcode
+ // and we only want to override this behavior if we have explicitly
+ // received a qHostInfo telling us otherwise
+ if (m_qHostInfo_is_valid != eLazyBoolYes) {
+ // On targets like MIPS, watchpoint exceptions are always generated
+ // before the instruction is executed. The connected target may not
+ // support qHostInfo or qWatchpointSupportInfo packets.
+ if (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel ||
+ atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el)
+ after = false;
else
- {
- // For MIPS, set m_watchpoints_trigger_after_instruction to eLazyBoolNo
- // if it is not calculated before.
- if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate &&
- (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel
- || atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el))
- m_watchpoints_trigger_after_instruction = eLazyBoolNo;
-
- after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo);
- }
- return error;
-}
-
-int
-GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec)
-{
- if (file_spec)
- {
- std::string path{file_spec.GetPath(false)};
- StreamString packet;
- packet.PutCString("QSetSTDIN:");
- packet.PutCStringAsRawHex8(path.c_str());
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
- }
- }
- return -1;
-}
+ after = true;
+ } else {
+ // For MIPS, set m_watchpoints_trigger_after_instruction to eLazyBoolNo
+ // if it is not calculated before.
+ if (m_watchpoints_trigger_after_instruction == eLazyBoolCalculate &&
+ (atype == llvm::Triple::mips || atype == llvm::Triple::mipsel ||
+ atype == llvm::Triple::mips64 || atype == llvm::Triple::mips64el))
+ m_watchpoints_trigger_after_instruction = eLazyBoolNo;
+
+ after = (m_watchpoints_trigger_after_instruction != eLazyBoolNo);
+ }
+ return error;
+}
+
+int GDBRemoteCommunicationClient::SetSTDIN(const FileSpec &file_spec) {
+ if (file_spec) {
+ std::string path{file_spec.GetPath(false)};
+ StreamString packet;
+ packet.PutCString("QSetSTDIN:");
+ packet.PutCStringAsRawHex8(path.c_str());
-int
-GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec)
-{
- if (file_spec)
- {
- std::string path{file_spec.GetPath(false)};
- StreamString packet;
- packet.PutCString("QSetSTDOUT:");
- packet.PutCStringAsRawHex8(path.c_str());
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
- }
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
}
- return -1;
+ }
+ return -1;
}
-int
-GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec)
-{
- if (file_spec)
- {
- std::string path{file_spec.GetPath(false)};
- StreamString packet;
- packet.PutCString("QSetSTDERR:");
- packet.PutCStringAsRawHex8(path.c_str());
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
- }
- }
- return -1;
-}
+int GDBRemoteCommunicationClient::SetSTDOUT(const FileSpec &file_spec) {
+ if (file_spec) {
+ std::string path{file_spec.GetPath(false)};
+ StreamString packet;
+ packet.PutCString("QSetSTDOUT:");
+ packet.PutCStringAsRawHex8(path.c_str());
-bool
-GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir)
-{
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse ("qGetWorkingDir", response, false) == PacketResult::Success)
- {
- if (response.IsUnsupportedResponse())
- return false;
- if (response.IsErrorResponse())
- return false;
- std::string cwd;
- response.GetHexByteString(cwd);
- working_dir.SetFile(cwd, false, GetHostArchitecture());
- return !cwd.empty();
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
}
- return false;
+ }
+ return -1;
}
-int
-GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir)
-{
- if (working_dir)
- {
- std::string path{working_dir.GetPath(false)};
- StreamString packet;
- packet.PutCString("QSetWorkingDir:");
- packet.PutCStringAsRawHex8(path.c_str());
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
- }
- }
- return -1;
-}
+int GDBRemoteCommunicationClient::SetSTDERR(const FileSpec &file_spec) {
+ if (file_spec) {
+ std::string path{file_spec.GetPath(false)};
+ StreamString packet;
+ packet.PutCString("QSetSTDERR:");
+ packet.PutCStringAsRawHex8(path.c_str());
-int
-GDBRemoteCommunicationClient::SetDisableASLR (bool enable)
-{
- char packet[32];
- const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDisableASLR:%i", enable ? 1 : 0);
- assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
}
- return -1;
-}
+ }
+ return -1;
+}
+
+bool GDBRemoteCommunicationClient::GetWorkingDir(FileSpec &working_dir) {
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qGetWorkingDir", response, false) ==
+ PacketResult::Success) {
+ if (response.IsUnsupportedResponse())
+ return false;
+ if (response.IsErrorResponse())
+ return false;
+ std::string cwd;
+ response.GetHexByteString(cwd);
+ working_dir.SetFile(cwd, false, GetHostArchitecture());
+ return !cwd.empty();
+ }
+ return false;
+}
+
+int GDBRemoteCommunicationClient::SetWorkingDir(const FileSpec &working_dir) {
+ if (working_dir) {
+ std::string path{working_dir.GetPath(false)};
+ StreamString packet;
+ packet.PutCString("QSetWorkingDir:");
+ packet.PutCStringAsRawHex8(path.c_str());
-int
-GDBRemoteCommunicationClient::SetDetachOnError (bool enable)
-{
- char packet[32];
- const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDetachOnError:%i", enable ? 1 : 0);
- assert (packet_len < (int)sizeof(packet));
StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return 0;
- uint8_t error = response.GetError();
- if (error)
- return error;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
}
- return -1;
-}
-
+ }
+ return -1;
+}
+
+int GDBRemoteCommunicationClient::SetDisableASLR(bool enable) {
+ char packet[32];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "QSetDisableASLR:%i", enable ? 1 : 0);
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ }
+ return -1;
+}
+
+int GDBRemoteCommunicationClient::SetDetachOnError(bool enable) {
+ char packet[32];
+ const int packet_len = ::snprintf(packet, sizeof(packet),
+ "QSetDetachOnError:%i", enable ? 1 : 0);
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return 0;
+ uint8_t error = response.GetError();
+ if (error)
+ return error;
+ }
+ return -1;
+}
+
+bool GDBRemoteCommunicationClient::DecodeProcessInfoResponse(
+ StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info) {
+ if (response.IsNormalResponse()) {
+ llvm::StringRef name;
+ llvm::StringRef value;
+ StringExtractor extractor;
-bool
-GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInstanceInfo &process_info)
-{
- if (response.IsNormalResponse())
- {
+ uint32_t cpu = LLDB_INVALID_CPUTYPE;
+ uint32_t sub = 0;
+ std::string vendor;
+ std::string os_type;
+
+ while (response.GetNameColonValue(name, value)) {
+ if (name.equals("pid")) {
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ value.getAsInteger(0, pid);
+ process_info.SetProcessID(pid);
+ } else if (name.equals("ppid")) {
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ value.getAsInteger(0, pid);
+ process_info.SetParentProcessID(pid);
+ } else if (name.equals("uid")) {
+ uint32_t uid = UINT32_MAX;
+ value.getAsInteger(0, uid);
+ process_info.SetUserID(uid);
+ } else if (name.equals("euid")) {
+ uint32_t uid = UINT32_MAX;
+ value.getAsInteger(0, uid);
+ process_info.SetEffectiveGroupID(uid);
+ } else if (name.equals("gid")) {
+ uint32_t gid = UINT32_MAX;
+ value.getAsInteger(0, gid);
+ process_info.SetGroupID(gid);
+ } else if (name.equals("egid")) {
+ uint32_t gid = UINT32_MAX;
+ value.getAsInteger(0, gid);
+ process_info.SetEffectiveGroupID(gid);
+ } else if (name.equals("triple")) {
+ StringExtractor extractor(value);
+ std::string triple;
+ extractor.GetHexByteString(triple);
+ process_info.GetArchitecture().SetTriple(triple.c_str());
+ } else if (name.equals("name")) {
+ StringExtractor extractor(value);
+ // The process name from ASCII hex bytes since we can't
+ // control the characters in a process name
std::string name;
- std::string value;
- StringExtractor extractor;
-
- uint32_t cpu = LLDB_INVALID_CPUTYPE;
- uint32_t sub = 0;
- std::string vendor;
- std::string os_type;
-
- while (response.GetNameColonValue(name, value))
- {
- if (name.compare("pid") == 0)
- {
- process_info.SetProcessID (StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0));
- }
- else if (name.compare("ppid") == 0)
- {
- process_info.SetParentProcessID (StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0));
- }
- else if (name.compare("uid") == 0)
- {
- process_info.SetUserID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0));
- }
- else if (name.compare("euid") == 0)
- {
- process_info.SetEffectiveUserID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0));
- }
- else if (name.compare("gid") == 0)
- {
- process_info.SetGroupID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0));
- }
- else if (name.compare("egid") == 0)
- {
- process_info.SetEffectiveGroupID (StringConvert::ToUInt32 (value.c_str(), UINT32_MAX, 0));
- }
- else if (name.compare("triple") == 0)
- {
- StringExtractor extractor;
- extractor.GetStringRef().swap(value);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (value);
- process_info.GetArchitecture ().SetTriple (value.c_str());
- }
- else if (name.compare("name") == 0)
- {
- StringExtractor extractor;
- // The process name from ASCII hex bytes since we can't
- // control the characters in a process name
- extractor.GetStringRef().swap(value);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (value);
- process_info.GetExecutableFile().SetFile (value.c_str(), false);
- }
- else if (name.compare("cputype") == 0)
- {
- cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16);
- }
- else if (name.compare("cpusubtype") == 0)
- {
- sub = StringConvert::ToUInt32 (value.c_str(), 0, 16);
- }
- else if (name.compare("vendor") == 0)
- {
- vendor = value;
- }
- else if (name.compare("ostype") == 0)
- {
- os_type = value;
- }
- }
-
- if (cpu != LLDB_INVALID_CPUTYPE && !vendor.empty() && !os_type.empty())
- {
- if (vendor == "apple")
- {
- process_info.GetArchitecture().SetArchitecture (eArchTypeMachO, cpu, sub);
- process_info.GetArchitecture().GetTriple().setVendorName (llvm::StringRef (vendor));
- process_info.GetArchitecture().GetTriple().setOSName (llvm::StringRef (os_type));
- }
- }
-
- if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
- return true;
- }
- return false;
-}
-
-bool
-GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info)
-{
- process_info.Clear();
-
- if (m_supports_qProcessInfoPID)
- {
- char packet[32];
- const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%" PRIu64, pid);
- assert (packet_len < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
- {
- return DecodeProcessInfoResponse (response, process_info);
- }
- else
- {
- m_supports_qProcessInfoPID = false;
- return false;
- }
- }
- return false;
-}
-
-bool
-GDBRemoteCommunicationClient::GetCurrentProcessInfo (bool allow_lazy)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
-
- if (allow_lazy)
- {
- if (m_qProcessInfo_is_valid == eLazyBoolYes)
- return true;
- if (m_qProcessInfo_is_valid == eLazyBoolNo)
- return false;
- }
-
- GetHostInfo ();
-
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse ("qProcessInfo", response, false) == PacketResult::Success)
- {
- if (response.IsNormalResponse())
- {
- std::string name;
- std::string value;
- uint32_t cpu = LLDB_INVALID_CPUTYPE;
- uint32_t sub = 0;
- std::string arch_name;
- std::string os_name;
- std::string vendor_name;
- std::string triple;
- std::string elf_abi;
- uint32_t pointer_byte_size = 0;
- StringExtractor extractor;
- ByteOrder byte_order = eByteOrderInvalid;
- uint32_t num_keys_decoded = 0;
- lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
- while (response.GetNameColonValue(name, value))
- {
- if (name.compare("cputype") == 0)
- {
- cpu = StringConvert::ToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16);
- if (cpu != LLDB_INVALID_CPUTYPE)
- ++num_keys_decoded;
- }
- else if (name.compare("cpusubtype") == 0)
- {
- sub = StringConvert::ToUInt32 (value.c_str(), 0, 16);
- if (sub != 0)
- ++num_keys_decoded;
- }
- else if (name.compare("triple") == 0)
- {
- StringExtractor extractor;
- extractor.GetStringRef().swap(value);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (triple);
- ++num_keys_decoded;
- }
- else if (name.compare("ostype") == 0)
- {
- os_name.swap (value);
- ++num_keys_decoded;
- }
- else if (name.compare("vendor") == 0)
- {
- vendor_name.swap(value);
- ++num_keys_decoded;
- }
- else if (name.compare("endian") == 0)
- {
- ++num_keys_decoded;
- if (value.compare("little") == 0)
- byte_order = eByteOrderLittle;
- else if (value.compare("big") == 0)
- byte_order = eByteOrderBig;
- else if (value.compare("pdp") == 0)
- byte_order = eByteOrderPDP;
- else
- --num_keys_decoded;
- }
- else if (name.compare("ptrsize") == 0)
- {
- pointer_byte_size = StringConvert::ToUInt32 (value.c_str(), 0, 16);
- if (pointer_byte_size != 0)
- ++num_keys_decoded;
- }
- else if (name.compare("pid") == 0)
- {
- pid = StringConvert::ToUInt64(value.c_str(), 0, 16);
- if (pid != LLDB_INVALID_PROCESS_ID)
- ++num_keys_decoded;
- }
- else if (name.compare("elf_abi") == 0)
- {
- elf_abi = value;
- ++num_keys_decoded;
- }
- }
- if (num_keys_decoded > 0)
- m_qProcessInfo_is_valid = eLazyBoolYes;
- if (pid != LLDB_INVALID_PROCESS_ID)
- {
- m_curr_pid_is_valid = eLazyBoolYes;
- m_curr_pid = pid;
- }
-
- // Set the ArchSpec from the triple if we have it.
- if (!triple.empty ())
- {
- m_process_arch.SetTriple (triple.c_str ());
- m_process_arch.SetFlags(elf_abi);
- if (pointer_byte_size)
- {
- assert (pointer_byte_size == m_process_arch.GetAddressByteSize());
- }
- }
- else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty())
- {
- llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name);
-
- assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat);
- switch (triple.getObjectFormat()) {
- case llvm::Triple::MachO:
- m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub);
- break;
- case llvm::Triple::ELF:
- m_process_arch.SetArchitecture (eArchTypeELF, cpu, sub);
- break;
- case llvm::Triple::COFF:
- m_process_arch.SetArchitecture (eArchTypeCOFF, cpu, sub);
- break;
- case llvm::Triple::UnknownObjectFormat:
- if (log)
- log->Printf("error: failed to determine target architecture");
- return false;
- }
-
- if (pointer_byte_size)
- {
- assert (pointer_byte_size == m_process_arch.GetAddressByteSize());
- }
- if (byte_order != eByteOrderInvalid)
- {
- assert (byte_order == m_process_arch.GetByteOrder());
- }
- m_process_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
- m_process_arch.GetTriple().setOSName(llvm::StringRef (os_name));
- m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name));
- m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name));
- }
- return true;
- }
- }
- else
- {
- m_qProcessInfo_is_valid = eLazyBoolNo;
- }
-
- return false;
-}
-
-
-uint32_t
-GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &match_info,
- ProcessInstanceInfoList &process_infos)
-{
- process_infos.Clear();
-
- if (m_supports_qfProcessInfo)
- {
- StreamString packet;
- packet.PutCString ("qfProcessInfo");
- if (!match_info.MatchAllProcesses())
- {
- packet.PutChar (':');
- const char *name = match_info.GetProcessInfo().GetName();
- bool has_name_match = false;
- if (name && name[0])
- {
- has_name_match = true;
- NameMatchType name_match_type = match_info.GetNameMatchType();
- switch (name_match_type)
- {
- case eNameMatchIgnore:
- has_name_match = false;
- break;
-
- case eNameMatchEquals:
- packet.PutCString ("name_match:equals;");
- break;
-
- case eNameMatchContains:
- packet.PutCString ("name_match:contains;");
- break;
-
- case eNameMatchStartsWith:
- packet.PutCString ("name_match:starts_with;");
- break;
-
- case eNameMatchEndsWith:
- packet.PutCString ("name_match:ends_with;");
- break;
-
- case eNameMatchRegularExpression:
- packet.PutCString ("name_match:regex;");
- break;
- }
- if (has_name_match)
- {
- packet.PutCString ("name:");
- packet.PutBytesAsRawHex8(name, ::strlen(name));
- packet.PutChar (';');
- }
- }
-
- if (match_info.GetProcessInfo().ProcessIDIsValid())
- packet.Printf("pid:%" PRIu64 ";",match_info.GetProcessInfo().GetProcessID());
- if (match_info.GetProcessInfo().ParentProcessIDIsValid())
- packet.Printf("parent_pid:%" PRIu64 ";",match_info.GetProcessInfo().GetParentProcessID());
- if (match_info.GetProcessInfo().UserIDIsValid())
- packet.Printf("uid:%u;",match_info.GetProcessInfo().GetUserID());
- if (match_info.GetProcessInfo().GroupIDIsValid())
- packet.Printf("gid:%u;",match_info.GetProcessInfo().GetGroupID());
- if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
- packet.Printf("euid:%u;",match_info.GetProcessInfo().GetEffectiveUserID());
- if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
- packet.Printf("egid:%u;",match_info.GetProcessInfo().GetEffectiveGroupID());
- if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
- packet.Printf("all_users:%u;",match_info.GetMatchAllUsers() ? 1 : 0);
- if (match_info.GetProcessInfo().GetArchitecture().IsValid())
- {
- const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture();
- const llvm::Triple &triple = match_arch.GetTriple();
- packet.PutCString("triple:");
- packet.PutCString(triple.getTriple().c_str());
- packet.PutChar (';');
- }
- }
- StringExtractorGDBRemote response;
- // Increase timeout as the first qfProcessInfo packet takes a long time
- // on Android. The value of 1min was arrived at empirically.
- GDBRemoteCommunication::ScopedTimeout timeout (*this, 60);
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success)
- {
- do
- {
- ProcessInstanceInfo process_info;
- if (!DecodeProcessInfoResponse (response, process_info))
- break;
- process_infos.Append(process_info);
- response.GetStringRef().clear();
- response.SetFilePos(0);
- } while (SendPacketAndWaitForResponse ("qsProcessInfo", strlen ("qsProcessInfo"), response, false) == PacketResult::Success);
- }
- else
- {
- m_supports_qfProcessInfo = false;
- return 0;
- }
- }
- return process_infos.GetSize();
-
-}
-
-bool
-GDBRemoteCommunicationClient::GetUserName (uint32_t uid, std::string &name)
-{
- if (m_supports_qUserName)
- {
- char packet[32];
- const int packet_len = ::snprintf (packet, sizeof (packet), "qUserName:%i", uid);
- assert (packet_len < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsNormalResponse())
- {
- // Make sure we parsed the right number of characters. The response is
- // the hex encoded user name and should make up the entire packet.
- // If there are any non-hex ASCII bytes, the length won't match below..
- if (response.GetHexByteString (name) * 2 == response.GetStringRef().size())
- return true;
- }
- }
- else
- {
- m_supports_qUserName = false;
- return false;
- }
- }
- return false;
-
-}
-
-bool
-GDBRemoteCommunicationClient::GetGroupName (uint32_t gid, std::string &name)
-{
- if (m_supports_qGroupName)
- {
- char packet[32];
- const int packet_len = ::snprintf (packet, sizeof (packet), "qGroupName:%i", gid);
- assert (packet_len < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsNormalResponse())
- {
- // Make sure we parsed the right number of characters. The response is
- // the hex encoded group name and should make up the entire packet.
- // If there are any non-hex ASCII bytes, the length won't match below..
- if (response.GetHexByteString (name) * 2 == response.GetStringRef().size())
- return true;
- }
- }
- else
- {
- m_supports_qGroupName = false;
- return false;
- }
- }
- return false;
-}
-
-bool
-GDBRemoteCommunicationClient::SetNonStopMode (const bool enable)
-{
- // Form non-stop packet request
+ extractor.GetHexByteString(name);
+ process_info.GetExecutableFile().SetFile(name, false);
+ } else if (name.equals("cputype")) {
+ value.getAsInteger(0, cpu);
+ } else if (name.equals("cpusubtype")) {
+ value.getAsInteger(0, sub);
+ } else if (name.equals("vendor")) {
+ vendor = value;
+ } else if (name.equals("ostype")) {
+ os_type = value;
+ }
+ }
+
+ if (cpu != LLDB_INVALID_CPUTYPE && !vendor.empty() && !os_type.empty()) {
+ if (vendor == "apple") {
+ process_info.GetArchitecture().SetArchitecture(eArchTypeMachO, cpu,
+ sub);
+ process_info.GetArchitecture().GetTriple().setVendorName(
+ llvm::StringRef(vendor));
+ process_info.GetArchitecture().GetTriple().setOSName(
+ llvm::StringRef(os_type));
+ }
+ }
+
+ if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
+ return true;
+ }
+ return false;
+}
+
+bool GDBRemoteCommunicationClient::GetProcessInfo(
+ lldb::pid_t pid, ProcessInstanceInfo &process_info) {
+ process_info.Clear();
+
+ if (m_supports_qProcessInfoPID) {
char packet[32];
- const int packet_len = ::snprintf(packet, sizeof(packet), "QNonStop:%1d", (int)enable);
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "qProcessInfoPID:%" PRIu64, pid);
assert(packet_len < (int)sizeof(packet));
-
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- // Send to target
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- if (response.IsOKResponse())
- return true;
-
- // Failed or not supported
- return false;
-
-}
-
-static void
-MakeSpeedTestPacket(StreamString &packet, uint32_t send_size, uint32_t recv_size)
-{
- packet.Clear();
- packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size);
- uint32_t bytes_left = send_size;
- while (bytes_left > 0)
- {
- if (bytes_left >= 26)
- {
- packet.PutCString("abcdefghijklmnopqrstuvwxyz");
- bytes_left -= 26;
- }
- else
- {
- packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz");
- bytes_left = 0;
- }
- }
-}
-
-template<typename T>
-T calculate_standard_deviation(const std::vector<T> &v)
-{
- T sum = std::accumulate(std::begin(v), std::end(v), T(0));
- T mean = sum / (T)v.size();
- T accum = T(0);
- std::for_each (std::begin(v), std::end(v), [&](const T d) {
- T delta = d - mean;
- accum += delta * delta;
- });
-
- T stdev = sqrt(accum / (v.size()-1));
- return stdev;
-}
-
-void
-GDBRemoteCommunicationClient::TestPacketSpeed (const uint32_t num_packets, uint32_t max_send, uint32_t max_recv, bool json, Stream &strm)
-{
- uint32_t i;
- TimeValue start_time, end_time;
- uint64_t total_time_nsec;
- if (SendSpeedTestPacket (0, 0))
- {
- StreamString packet;
- if (json)
- strm.Printf("{ \"packet_speeds\" : {\n \"num_packets\" : %u,\n \"results\" : [", num_packets);
- else
- strm.Printf("Testing sending %u packets of various sizes:\n", num_packets);
- strm.Flush();
-
- uint32_t result_idx = 0;
- uint32_t send_size;
- std::vector<float> packet_times;
-
- for (send_size = 0; send_size <= max_send; send_size ? send_size *= 2 : send_size = 4)
- {
- for (uint32_t recv_size = 0; recv_size <= max_recv; recv_size ? recv_size *= 2 : recv_size = 4)
- {
- MakeSpeedTestPacket (packet, send_size, recv_size);
-
- packet_times.clear();
- // Test how long it takes to send 'num_packets' packets
- start_time = TimeValue::Now();
- for (i=0; i<num_packets; ++i)
- {
- TimeValue packet_start_time = TimeValue::Now();
- StringExtractorGDBRemote response;
- SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false);
- TimeValue packet_end_time = TimeValue::Now();
- uint64_t packet_time_nsec = packet_end_time.GetAsNanoSecondsSinceJan1_1970() - packet_start_time.GetAsNanoSecondsSinceJan1_1970();
- packet_times.push_back((float)packet_time_nsec);
- }
- end_time = TimeValue::Now();
- total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
-
- float packets_per_second = (((float)num_packets)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
- float total_ms = (float)total_time_nsec/(float)TimeValue::NanoSecPerMilliSec;
- float average_ms_per_packet = total_ms / num_packets;
- const float standard_deviation = calculate_standard_deviation<float>(packet_times);
- if (json)
- {
- strm.Printf ("%s\n {\"send_size\" : %6" PRIu32 ", \"recv_size\" : %6" PRIu32 ", \"total_time_nsec\" : %12" PRIu64 ", \"standard_deviation_nsec\" : %9" PRIu64 " }", result_idx > 0 ? "," : "", send_size, recv_size, total_time_nsec, (uint64_t)standard_deviation);
- ++result_idx;
- }
- else
- {
- strm.Printf ("qSpeedTest(send=%-7u, recv=%-7u) in %" PRIu64 ".%9.9" PRIu64 " sec for %9.2f packets/sec (%10.6f ms per packet) with standard deviation of %10.6f ms\n",
- send_size,
- recv_size,
- total_time_nsec / TimeValue::NanoSecPerSec,
- total_time_nsec % TimeValue::NanoSecPerSec,
- packets_per_second,
- average_ms_per_packet,
- standard_deviation/(float)TimeValue::NanoSecPerMilliSec);
- }
- strm.Flush();
- }
- }
-
- const uint64_t k_recv_amount = 4*1024*1024; // Receive amount in bytes
-
- const float k_recv_amount_mb = (float)k_recv_amount/(1024.0f*1024.0f);
- if (json)
- strm.Printf("\n ]\n },\n \"download_speed\" : {\n \"byte_size\" : %" PRIu64 ",\n \"results\" : [", k_recv_amount);
- else
- strm.Printf("Testing receiving %2.1fMB of data using varying receive packet sizes:\n", k_recv_amount_mb);
- strm.Flush();
- send_size = 0;
- result_idx = 0;
- for (uint32_t recv_size = 32; recv_size <= max_recv; recv_size *= 2)
- {
- MakeSpeedTestPacket (packet, send_size, recv_size);
-
- // If we have a receive size, test how long it takes to receive 4MB of data
- if (recv_size > 0)
- {
- start_time = TimeValue::Now();
- uint32_t bytes_read = 0;
- uint32_t packet_count = 0;
- while (bytes_read < k_recv_amount)
- {
- StringExtractorGDBRemote response;
- SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false);
- bytes_read += recv_size;
- ++packet_count;
- }
- end_time = TimeValue::Now();
- total_time_nsec = end_time.GetAsNanoSecondsSinceJan1_1970() - start_time.GetAsNanoSecondsSinceJan1_1970();
- float mb_second = ((((float)k_recv_amount)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec) / (1024.0*1024.0);
- float packets_per_second = (((float)packet_count)/(float)total_time_nsec) * (float)TimeValue::NanoSecPerSec;
- float total_ms = (float)total_time_nsec/(float)TimeValue::NanoSecPerMilliSec;
- float average_ms_per_packet = total_ms / packet_count;
-
- if (json)
- {
- strm.Printf ("%s\n {\"send_size\" : %6" PRIu32 ", \"recv_size\" : %6" PRIu32 ", \"total_time_nsec\" : %12" PRIu64 " }", result_idx > 0 ? "," : "", send_size, recv_size, total_time_nsec);
- ++result_idx;
- }
- else
- {
- strm.Printf ("qSpeedTest(send=%-7u, recv=%-7u) %6u packets needed to receive %2.1fMB in %" PRIu64 ".%9.9" PRIu64 " sec for %f MB/sec for %9.2f packets/sec (%10.6f ms per packet)\n",
- send_size,
- recv_size,
- packet_count,
- k_recv_amount_mb,
- total_time_nsec / TimeValue::NanoSecPerSec,
- total_time_nsec % TimeValue::NanoSecPerSec,
- mb_second,
- packets_per_second,
- average_ms_per_packet);
- }
- strm.Flush();
- }
- }
- if (json)
- strm.Printf("\n ]\n }\n}\n");
- else
- strm.EOL();
- }
-}
-
-bool
-GDBRemoteCommunicationClient::SendSpeedTestPacket (uint32_t send_size, uint32_t recv_size)
-{
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ return DecodeProcessInfoResponse(response, process_info);
+ } else {
+ m_supports_qProcessInfoPID = false;
+ return false;
+ }
+ }
+ return false;
+}
+
+bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
+ GDBR_LOG_PACKETS));
+
+ if (allow_lazy) {
+ if (m_qProcessInfo_is_valid == eLazyBoolYes)
+ return true;
+ if (m_qProcessInfo_is_valid == eLazyBoolNo)
+ return false;
+ }
+
+ GetHostInfo();
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qProcessInfo", response, false) ==
+ PacketResult::Success) {
+ if (response.IsNormalResponse()) {
+ llvm::StringRef name;
+ llvm::StringRef value;
+ uint32_t cpu = LLDB_INVALID_CPUTYPE;
+ uint32_t sub = 0;
+ std::string arch_name;
+ std::string os_name;
+ std::string vendor_name;
+ std::string triple;
+ std::string elf_abi;
+ uint32_t pointer_byte_size = 0;
+ StringExtractor extractor;
+ ByteOrder byte_order = eByteOrderInvalid;
+ uint32_t num_keys_decoded = 0;
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ while (response.GetNameColonValue(name, value)) {
+ if (name.equals("cputype")) {
+ if (!value.getAsInteger(16, cpu))
+ ++num_keys_decoded;
+ } else if (name.equals("cpusubtype")) {
+ if (!value.getAsInteger(16, sub))
+ ++num_keys_decoded;
+ } else if (name.equals("triple")) {
+ StringExtractor extractor(value);
+ extractor.GetHexByteString(triple);
+ ++num_keys_decoded;
+ } else if (name.equals("ostype")) {
+ os_name = value;
+ ++num_keys_decoded;
+ } else if (name.equals("vendor")) {
+ vendor_name = value;
+ ++num_keys_decoded;
+ } else if (name.equals("endian")) {
+ byte_order = llvm::StringSwitch<lldb::ByteOrder>(value)
+ .Case("little", eByteOrderLittle)
+ .Case("big", eByteOrderBig)
+ .Case("pdp", eByteOrderPDP)
+ .Default(eByteOrderInvalid);
+ if (byte_order != eByteOrderInvalid)
+ ++num_keys_decoded;
+ } else if (name.equals("ptrsize")) {
+ if (!value.getAsInteger(16, pointer_byte_size))
+ ++num_keys_decoded;
+ } else if (name.equals("pid")) {
+ if (!value.getAsInteger(16, pid))
+ ++num_keys_decoded;
+ } else if (name.equals("elf_abi")) {
+ elf_abi = value;
+ ++num_keys_decoded;
+ }
+ }
+ if (num_keys_decoded > 0)
+ m_qProcessInfo_is_valid = eLazyBoolYes;
+ if (pid != LLDB_INVALID_PROCESS_ID) {
+ m_curr_pid_is_valid = eLazyBoolYes;
+ m_curr_pid = pid;
+ }
+
+ // Set the ArchSpec from the triple if we have it.
+ if (!triple.empty()) {
+ m_process_arch.SetTriple(triple.c_str());
+ m_process_arch.SetFlags(elf_abi);
+ if (pointer_byte_size) {
+ assert(pointer_byte_size == m_process_arch.GetAddressByteSize());
+ }
+ } else if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() &&
+ !vendor_name.empty()) {
+ llvm::Triple triple(llvm::Twine("-") + vendor_name + "-" + os_name);
+
+ assert(triple.getObjectFormat() != llvm::Triple::UnknownObjectFormat);
+ switch (triple.getObjectFormat()) {
+ case llvm::Triple::MachO:
+ m_process_arch.SetArchitecture(eArchTypeMachO, cpu, sub);
+ break;
+ case llvm::Triple::ELF:
+ m_process_arch.SetArchitecture(eArchTypeELF, cpu, sub);
+ break;
+ case llvm::Triple::COFF:
+ m_process_arch.SetArchitecture(eArchTypeCOFF, cpu, sub);
+ break;
+ case llvm::Triple::UnknownObjectFormat:
+ if (log)
+ log->Printf("error: failed to determine target architecture");
+ return false;
+ }
+
+ if (pointer_byte_size) {
+ assert(pointer_byte_size == m_process_arch.GetAddressByteSize());
+ }
+ if (byte_order != eByteOrderInvalid) {
+ assert(byte_order == m_process_arch.GetByteOrder());
+ }
+ m_process_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name));
+ m_process_arch.GetTriple().setOSName(llvm::StringRef(os_name));
+ m_host_arch.GetTriple().setVendorName(llvm::StringRef(vendor_name));
+ m_host_arch.GetTriple().setOSName(llvm::StringRef(os_name));
+ }
+ return true;
+ }
+ } else {
+ m_qProcessInfo_is_valid = eLazyBoolNo;
+ }
+
+ return false;
+}
+
+uint32_t GDBRemoteCommunicationClient::FindProcesses(
+ const ProcessInstanceInfoMatch &match_info,
+ ProcessInstanceInfoList &process_infos) {
+ process_infos.Clear();
+
+ if (m_supports_qfProcessInfo) {
StreamString packet;
- packet.Printf ("qSpeedTest:response_size:%i;data:", recv_size);
- uint32_t bytes_left = send_size;
- while (bytes_left > 0)
- {
- if (bytes_left >= 26)
- {
- packet.PutCString("abcdefghijklmnopqrstuvwxyz");
- bytes_left -= 26;
- }
- else
- {
- packet.Printf ("%*.*s;", bytes_left, bytes_left, "abcdefghijklmnopqrstuvwxyz");
- bytes_left = 0;
- }
+ packet.PutCString("qfProcessInfo");
+ if (!match_info.MatchAllProcesses()) {
+ packet.PutChar(':');
+ const char *name = match_info.GetProcessInfo().GetName();
+ bool has_name_match = false;
+ if (name && name[0]) {
+ has_name_match = true;
+ NameMatchType name_match_type = match_info.GetNameMatchType();
+ switch (name_match_type) {
+ case eNameMatchIgnore:
+ has_name_match = false;
+ break;
+
+ case eNameMatchEquals:
+ packet.PutCString("name_match:equals;");
+ break;
+
+ case eNameMatchContains:
+ packet.PutCString("name_match:contains;");
+ break;
+
+ case eNameMatchStartsWith:
+ packet.PutCString("name_match:starts_with;");
+ break;
+
+ case eNameMatchEndsWith:
+ packet.PutCString("name_match:ends_with;");
+ break;
+
+ case eNameMatchRegularExpression:
+ packet.PutCString("name_match:regex;");
+ break;
+ }
+ if (has_name_match) {
+ packet.PutCString("name:");
+ packet.PutBytesAsRawHex8(name, ::strlen(name));
+ packet.PutChar(';');
+ }
+ }
+
+ if (match_info.GetProcessInfo().ProcessIDIsValid())
+ packet.Printf("pid:%" PRIu64 ";",
+ match_info.GetProcessInfo().GetProcessID());
+ if (match_info.GetProcessInfo().ParentProcessIDIsValid())
+ packet.Printf("parent_pid:%" PRIu64 ";",
+ match_info.GetProcessInfo().GetParentProcessID());
+ if (match_info.GetProcessInfo().UserIDIsValid())
+ packet.Printf("uid:%u;", match_info.GetProcessInfo().GetUserID());
+ if (match_info.GetProcessInfo().GroupIDIsValid())
+ packet.Printf("gid:%u;", match_info.GetProcessInfo().GetGroupID());
+ if (match_info.GetProcessInfo().EffectiveUserIDIsValid())
+ packet.Printf("euid:%u;",
+ match_info.GetProcessInfo().GetEffectiveUserID());
+ if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
+ packet.Printf("egid:%u;",
+ match_info.GetProcessInfo().GetEffectiveGroupID());
+ if (match_info.GetProcessInfo().EffectiveGroupIDIsValid())
+ packet.Printf("all_users:%u;", match_info.GetMatchAllUsers() ? 1 : 0);
+ if (match_info.GetProcessInfo().GetArchitecture().IsValid()) {
+ const ArchSpec &match_arch =
+ match_info.GetProcessInfo().GetArchitecture();
+ const llvm::Triple &triple = match_arch.GetTriple();
+ packet.PutCString("triple:");
+ packet.PutCString(triple.getTriple());
+ packet.PutChar(';');
+ }
}
-
StringExtractorGDBRemote response;
- return SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) == PacketResult::Success;
-}
-
-bool
-GDBRemoteCommunicationClient::LaunchGDBServer (const char *remote_accept_hostname,
- lldb::pid_t &pid,
- uint16_t &port,
- std::string &socket_name)
-{
- pid = LLDB_INVALID_PROCESS_ID;
- port = 0;
- socket_name.clear();
-
+ // Increase timeout as the first qfProcessInfo packet takes a long time
+ // on Android. The value of 1min was arrived at empirically.
+ ScopedTimeout timeout(*this, minutes(1));
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success) {
+ do {
+ ProcessInstanceInfo process_info;
+ if (!DecodeProcessInfoResponse(response, process_info))
+ break;
+ process_infos.Append(process_info);
+ response.GetStringRef().clear();
+ response.SetFilePos(0);
+ } while (SendPacketAndWaitForResponse("qsProcessInfo", response, false) ==
+ PacketResult::Success);
+ } else {
+ m_supports_qfProcessInfo = false;
+ return 0;
+ }
+ }
+ return process_infos.GetSize();
+}
+
+bool GDBRemoteCommunicationClient::GetUserName(uint32_t uid,
+ std::string &name) {
+ if (m_supports_qUserName) {
+ char packet[32];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "qUserName:%i", uid);
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
StringExtractorGDBRemote response;
- StreamString stream;
- stream.PutCString("qLaunchGDBServer;");
- std::string hostname;
- if (remote_accept_hostname && remote_accept_hostname[0])
- hostname = remote_accept_hostname;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsNormalResponse()) {
+ // Make sure we parsed the right number of characters. The response is
+ // the hex encoded user name and should make up the entire packet.
+ // If there are any non-hex ASCII bytes, the length won't match below..
+ if (response.GetHexByteString(name) * 2 ==
+ response.GetStringRef().size())
+ return true;
+ }
+ } else {
+ m_supports_qUserName = false;
+ return false;
+ }
+ }
+ return false;
+}
+
+bool GDBRemoteCommunicationClient::GetGroupName(uint32_t gid,
+ std::string &name) {
+ if (m_supports_qGroupName) {
+ char packet[32];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "qGroupName:%i", gid);
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsNormalResponse()) {
+ // Make sure we parsed the right number of characters. The response is
+ // the hex encoded group name and should make up the entire packet.
+ // If there are any non-hex ASCII bytes, the length won't match below..
+ if (response.GetHexByteString(name) * 2 ==
+ response.GetStringRef().size())
+ return true;
+ }
+ } else {
+ m_supports_qGroupName = false;
+ return false;
+ }
+ }
+ return false;
+}
+
+bool GDBRemoteCommunicationClient::SetNonStopMode(const bool enable) {
+ // Form non-stop packet request
+ char packet[32];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "QNonStop:%1d", (int)enable);
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+
+ StringExtractorGDBRemote response;
+ // Send to target
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success)
+ if (response.IsOKResponse())
+ return true;
+
+ // Failed or not supported
+ return false;
+}
+
+static void MakeSpeedTestPacket(StreamString &packet, uint32_t send_size,
+ uint32_t recv_size) {
+ packet.Clear();
+ packet.Printf("qSpeedTest:response_size:%i;data:", recv_size);
+ uint32_t bytes_left = send_size;
+ while (bytes_left > 0) {
+ if (bytes_left >= 26) {
+ packet.PutCString("abcdefghijklmnopqrstuvwxyz");
+ bytes_left -= 26;
+ } else {
+ packet.Printf("%*.*s;", bytes_left, bytes_left,
+ "abcdefghijklmnopqrstuvwxyz");
+ bytes_left = 0;
+ }
+ }
+}
+
+duration<float>
+calculate_standard_deviation(const std::vector<duration<float>> &v) {
+ using Dur = duration<float>;
+ Dur sum = std::accumulate(std::begin(v), std::end(v), Dur());
+ Dur mean = sum / v.size();
+ float accum = 0;
+ for (auto d : v) {
+ float delta = (d - mean).count();
+ accum += delta * delta;
+ };
+
+ return Dur(sqrtf(accum / (v.size() - 1)));
+}
+
+void GDBRemoteCommunicationClient::TestPacketSpeed(const uint32_t num_packets,
+ uint32_t max_send,
+ uint32_t max_recv,
+ uint64_t recv_amount,
+ bool json, Stream &strm) {
+ uint32_t i;
+ if (SendSpeedTestPacket(0, 0)) {
+ StreamString packet;
+ if (json)
+ strm.Printf("{ \"packet_speeds\" : {\n \"num_packets\" : %u,\n "
+ "\"results\" : [",
+ num_packets);
else
- {
- if (HostInfo::GetHostname(hostname))
- {
- // Make the GDB server we launch only accept connections from this host
- stream.Printf("host:%s;", hostname.c_str());
- }
- else
- {
- // Make the GDB server we launch accept connections from any host since we can't figure out the hostname
- stream.Printf("host:*;");
+ strm.Printf("Testing sending %u packets of various sizes:\n",
+ num_packets);
+ strm.Flush();
+
+ uint32_t result_idx = 0;
+ uint32_t send_size;
+ std::vector<duration<float>> packet_times;
+
+ for (send_size = 0; send_size <= max_send;
+ send_size ? send_size *= 2 : send_size = 4) {
+ for (uint32_t recv_size = 0; recv_size <= max_recv;
+ recv_size ? recv_size *= 2 : recv_size = 4) {
+ MakeSpeedTestPacket(packet, send_size, recv_size);
+
+ packet_times.clear();
+ // Test how long it takes to send 'num_packets' packets
+ const auto start_time = steady_clock::now();
+ for (i = 0; i < num_packets; ++i) {
+ const auto packet_start_time = steady_clock::now();
+ StringExtractorGDBRemote response;
+ SendPacketAndWaitForResponse(packet.GetString(), response, false);
+ const auto packet_end_time = steady_clock::now();
+ packet_times.push_back(packet_end_time - packet_start_time);
+ }
+ const auto end_time = steady_clock::now();
+ const auto total_time = end_time - start_time;
+
+ float packets_per_second =
+ ((float)num_packets) / duration<float>(total_time).count();
+ auto average_per_packet = total_time / num_packets;
+ const duration<float> standard_deviation =
+ calculate_standard_deviation(packet_times);
+ if (json) {
+ strm.Printf("%s\n {\"send_size\" : %6" PRIu32
+ ", \"recv_size\" : %6" PRIu32
+ ", \"total_time_nsec\" : %12" PRIu64
+ ", \"standard_deviation_nsec\" : %9" PRIu64 " }",
+ result_idx > 0 ? "," : "", send_size, recv_size,
+ duration_cast<nanoseconds>(total_time).count(),
+ duration_cast<nanoseconds>(standard_deviation).count());
+ ++result_idx;
+ } else {
+ strm.Printf(
+ "qSpeedTest(send=%-7u, recv=%-7u) in %.9f"
+ " sec for %9.2f packets/sec (%10.6f ms per packet) with standard "
+ "deviation of %10.6f ms\n",
+ send_size, recv_size, duration<float>(total_time).count(),
+ packets_per_second,
+ duration<float, std::milli>(average_per_packet).count(),
+ duration<float, std::milli>(standard_deviation).count());
}
+ strm.Flush();
+ }
}
- const char *packet = stream.GetData();
- int packet_len = stream.GetSize();
-
- // give the process a few seconds to startup
- GDBRemoteCommunication::ScopedTimeout timeout (*this, 10);
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- std::string name;
- std::string value;
- StringExtractor extractor;
- while (response.GetNameColonValue(name, value))
- {
- if (name.compare("port") == 0)
- port = StringConvert::ToUInt32(value.c_str(), 0, 0);
- else if (name.compare("pid") == 0)
- pid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_PROCESS_ID, 0);
- else if (name.compare("socket_name") == 0)
- {
- extractor.GetStringRef().swap(value);
- extractor.SetFilePos(0);
- extractor.GetHexByteString(value);
-
- socket_name = value;
- }
+ const float k_recv_amount_mb = (float)recv_amount / (1024.0f * 1024.0f);
+ if (json)
+ strm.Printf("\n ]\n },\n \"download_speed\" : {\n \"byte_size\" "
+ ": %" PRIu64 ",\n \"results\" : [",
+ recv_amount);
+ else
+ strm.Printf("Testing receiving %2.1fMB of data using varying receive "
+ "packet sizes:\n",
+ k_recv_amount_mb);
+ strm.Flush();
+ send_size = 0;
+ result_idx = 0;
+ for (uint32_t recv_size = 32; recv_size <= max_recv; recv_size *= 2) {
+ MakeSpeedTestPacket(packet, send_size, recv_size);
+
+ // If we have a receive size, test how long it takes to receive 4MB of
+ // data
+ if (recv_size > 0) {
+ const auto start_time = steady_clock::now();
+ uint32_t bytes_read = 0;
+ uint32_t packet_count = 0;
+ while (bytes_read < recv_amount) {
+ StringExtractorGDBRemote response;
+ SendPacketAndWaitForResponse(packet.GetString(), response, false);
+ bytes_read += recv_size;
+ ++packet_count;
+ }
+ const auto end_time = steady_clock::now();
+ const auto total_time = end_time - start_time;
+ float mb_second = ((float)recv_amount) /
+ duration<float>(total_time).count() /
+ (1024.0 * 1024.0);
+ float packets_per_second =
+ ((float)packet_count) / duration<float>(total_time).count();
+ const auto average_per_packet = total_time / packet_count;
+
+ if (json) {
+ strm.Printf("%s\n {\"send_size\" : %6" PRIu32
+ ", \"recv_size\" : %6" PRIu32
+ ", \"total_time_nsec\" : %12" PRIu64 " }",
+ result_idx > 0 ? "," : "", send_size, recv_size,
+ duration_cast<nanoseconds>(total_time).count());
+ ++result_idx;
+ } else {
+ strm.Printf("qSpeedTest(send=%-7u, recv=%-7u) %6u packets needed to "
+ "receive %2.1fMB in %.9f"
+ " sec for %f MB/sec for %9.2f packets/sec (%10.6f ms per "
+ "packet)\n",
+ send_size, recv_size, packet_count, k_recv_amount_mb,
+ duration<float>(total_time).count(), mb_second,
+ packets_per_second,
+ duration<float, std::milli>(average_per_packet).count());
}
- return true;
+ strm.Flush();
+ }
}
- return false;
+ if (json)
+ strm.Printf("\n ]\n }\n}\n");
+ else
+ strm.EOL();
+ }
+}
+
+bool GDBRemoteCommunicationClient::SendSpeedTestPacket(uint32_t send_size,
+ uint32_t recv_size) {
+ StreamString packet;
+ packet.Printf("qSpeedTest:response_size:%i;data:", recv_size);
+ uint32_t bytes_left = send_size;
+ while (bytes_left > 0) {
+ if (bytes_left >= 26) {
+ packet.PutCString("abcdefghijklmnopqrstuvwxyz");
+ bytes_left -= 26;
+ } else {
+ packet.Printf("%*.*s;", bytes_left, bytes_left,
+ "abcdefghijklmnopqrstuvwxyz");
+ bytes_left = 0;
+ }
+ }
+
+ StringExtractorGDBRemote response;
+ return SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ PacketResult::Success;
+}
+
+bool GDBRemoteCommunicationClient::LaunchGDBServer(
+ const char *remote_accept_hostname, lldb::pid_t &pid, uint16_t &port,
+ std::string &socket_name) {
+ pid = LLDB_INVALID_PROCESS_ID;
+ port = 0;
+ socket_name.clear();
+
+ StringExtractorGDBRemote response;
+ StreamString stream;
+ stream.PutCString("qLaunchGDBServer;");
+ std::string hostname;
+ if (remote_accept_hostname && remote_accept_hostname[0])
+ hostname = remote_accept_hostname;
+ else {
+ if (HostInfo::GetHostname(hostname)) {
+ // Make the GDB server we launch only accept connections from this host
+ stream.Printf("host:%s;", hostname.c_str());
+ } else {
+ // Make the GDB server we launch accept connections from any host since we
+ // can't figure out the hostname
+ stream.Printf("host:*;");
+ }
+ }
+ // give the process a few seconds to startup
+ ScopedTimeout timeout(*this, seconds(10));
+
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ llvm::StringRef name;
+ llvm::StringRef value;
+ while (response.GetNameColonValue(name, value)) {
+ if (name.equals("port"))
+ value.getAsInteger(0, port);
+ else if (name.equals("pid"))
+ value.getAsInteger(0, pid);
+ else if (name.compare("socket_name") == 0) {
+ StringExtractor extractor(value);
+ extractor.GetHexByteString(socket_name);
+ }
+ }
+ return true;
+ }
+ return false;
}
-size_t
-GDBRemoteCommunicationClient::QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls)
-{
- connection_urls.clear();
+size_t GDBRemoteCommunicationClient::QueryGDBServer(
+ std::vector<std::pair<uint16_t, std::string>> &connection_urls) {
+ connection_urls.clear();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) != PacketResult::Success)
- return 0;
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qQueryGDBServer", response, false) !=
+ PacketResult::Success)
+ return 0;
- StructuredData::ObjectSP data = StructuredData::ParseJSON(response.GetStringRef());
- if (!data)
- return 0;
+ StructuredData::ObjectSP data =
+ StructuredData::ParseJSON(response.GetStringRef());
+ if (!data)
+ return 0;
- StructuredData::Array* array = data->GetAsArray();
- if (!array)
- return 0;
+ StructuredData::Array *array = data->GetAsArray();
+ if (!array)
+ return 0;
- for (size_t i = 0, count = array->GetSize(); i < count; ++i)
- {
- StructuredData::Dictionary* element = nullptr;
- if (!array->GetItemAtIndexAsDictionary(i, element))
- continue;
+ for (size_t i = 0, count = array->GetSize(); i < count; ++i) {
+ StructuredData::Dictionary *element = nullptr;
+ if (!array->GetItemAtIndexAsDictionary(i, element))
+ continue;
- uint16_t port = 0;
- if (StructuredData::ObjectSP port_osp = element->GetValueForKey(llvm::StringRef("port")))
- port = port_osp->GetIntegerValue(0);
+ uint16_t port = 0;
+ if (StructuredData::ObjectSP port_osp =
+ element->GetValueForKey(llvm::StringRef("port")))
+ port = port_osp->GetIntegerValue(0);
- std::string socket_name;
- if (StructuredData::ObjectSP socket_name_osp = element->GetValueForKey(llvm::StringRef("socket_name")))
- socket_name = socket_name_osp->GetStringValue();
+ std::string socket_name;
+ if (StructuredData::ObjectSP socket_name_osp =
+ element->GetValueForKey(llvm::StringRef("socket_name")))
+ socket_name = socket_name_osp->GetStringValue();
- if (port != 0 || !socket_name.empty())
- connection_urls.emplace_back(port, socket_name);
- }
- return connection_urls.size();
+ if (port != 0 || !socket_name.empty())
+ connection_urls.emplace_back(port, socket_name);
+ }
+ return connection_urls.size();
}
-bool
-GDBRemoteCommunicationClient::KillSpawnedProcess (lldb::pid_t pid)
-{
- StreamString stream;
- stream.Printf ("qKillSpawnedProcess:%" PRId64 , pid);
- const char *packet = stream.GetData();
- int packet_len = stream.GetSize();
+bool GDBRemoteCommunicationClient::KillSpawnedProcess(lldb::pid_t pid) {
+ StreamString stream;
+ stream.Printf("qKillSpawnedProcess:%" PRId64, pid);
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- return true;
- }
- return false;
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse())
+ return true;
+ }
+ return false;
}
-bool
-GDBRemoteCommunicationClient::SetCurrentThread (uint64_t tid)
-{
- if (m_curr_tid == tid)
- return true;
-
- char packet[32];
- int packet_len;
- if (tid == UINT64_MAX)
- packet_len = ::snprintf (packet, sizeof(packet), "Hg-1");
- else
- packet_len = ::snprintf (packet, sizeof(packet), "Hg%" PRIx64, tid);
- assert (packet_len + 1 < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- {
- m_curr_tid = tid;
- return true;
- }
+bool GDBRemoteCommunicationClient::SetCurrentThread(uint64_t tid) {
+ if (m_curr_tid == tid)
+ return true;
- /*
- * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hg packet.
- * The reply from '?' packet could be as simple as 'S05'. There is no packet which can
- * give us pid and/or tid. Assume pid=tid=1 in such cases.
- */
- if (response.IsUnsupportedResponse() && IsConnected())
- {
- m_curr_tid = 1;
- return true;
- }
- }
- return false;
-}
+ char packet[32];
+ int packet_len;
+ if (tid == UINT64_MAX)
+ packet_len = ::snprintf(packet, sizeof(packet), "Hg-1");
+ else
+ packet_len = ::snprintf(packet, sizeof(packet), "Hg%" PRIx64, tid);
+ assert(packet_len + 1 < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_curr_tid = tid;
+ return true;
+ }
+
+ /*
+ * Connected bare-iron target (like YAMON gdb-stub) may not have support for
+ * Hg packet.
+ * The reply from '?' packet could be as simple as 'S05'. There is no packet
+ * which can
+ * give us pid and/or tid. Assume pid=tid=1 in such cases.
+ */
+ if (response.IsUnsupportedResponse() && IsConnected()) {
+ m_curr_tid = 1;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool GDBRemoteCommunicationClient::SetCurrentThreadForRun(uint64_t tid) {
+ if (m_curr_tid_run == tid)
+ return true;
-bool
-GDBRemoteCommunicationClient::SetCurrentThreadForRun (uint64_t tid)
-{
- if (m_curr_tid_run == tid)
+ char packet[32];
+ int packet_len;
+ if (tid == UINT64_MAX)
+ packet_len = ::snprintf(packet, sizeof(packet), "Hc-1");
+ else
+ packet_len = ::snprintf(packet, sizeof(packet), "Hc%" PRIx64, tid);
+
+ assert(packet_len + 1 < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ m_curr_tid_run = tid;
+ return true;
+ }
+
+ /*
+ * Connected bare-iron target (like YAMON gdb-stub) may not have support for
+ * Hc packet.
+ * The reply from '?' packet could be as simple as 'S05'. There is no packet
+ * which can
+ * give us pid and/or tid. Assume pid=tid=1 in such cases.
+ */
+ if (response.IsUnsupportedResponse() && IsConnected()) {
+ m_curr_tid_run = 1;
+ return true;
+ }
+ }
+ return false;
+}
+
+bool GDBRemoteCommunicationClient::GetStopReply(
+ StringExtractorGDBRemote &response) {
+ if (SendPacketAndWaitForResponse("?", response, false) ==
+ PacketResult::Success)
+ return response.IsNormalResponse();
+ return false;
+}
+
+bool GDBRemoteCommunicationClient::GetThreadStopInfo(
+ lldb::tid_t tid, StringExtractorGDBRemote &response) {
+ if (m_supports_qThreadStopInfo) {
+ char packet[256];
+ int packet_len =
+ ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ if (SendPacketAndWaitForResponse(packet, response, false) ==
+ PacketResult::Success) {
+ if (response.IsUnsupportedResponse())
+ m_supports_qThreadStopInfo = false;
+ else if (response.IsNormalResponse())
return true;
-
- char packet[32];
- int packet_len;
- if (tid == UINT64_MAX)
- packet_len = ::snprintf (packet, sizeof(packet), "Hc-1");
- else
- packet_len = ::snprintf (packet, sizeof(packet), "Hc%" PRIx64, tid);
-
- assert (packet_len + 1 < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- {
- m_curr_tid_run = tid;
- return true;
- }
-
- /*
- * Connected bare-iron target (like YAMON gdb-stub) may not have support for Hc packet.
- * The reply from '?' packet could be as simple as 'S05'. There is no packet which can
- * give us pid and/or tid. Assume pid=tid=1 in such cases.
- */
- if (response.IsUnsupportedResponse() && IsConnected())
- {
- m_curr_tid_run = 1;
- return true;
- }
+ else
+ return false;
+ } else {
+ m_supports_qThreadStopInfo = false;
}
- return false;
+ }
+ return false;
}
-bool
-GDBRemoteCommunicationClient::GetStopReply (StringExtractorGDBRemote &response)
-{
- if (SendPacketAndWaitForResponse("?", 1, response, false) == PacketResult::Success)
- return response.IsNormalResponse();
- return false;
-}
+uint8_t GDBRemoteCommunicationClient::SendGDBStoppointTypePacket(
+ GDBStoppointType type, bool insert, addr_t addr, uint32_t length) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64,
+ __FUNCTION__, insert ? "add" : "remove", addr);
-bool
-GDBRemoteCommunicationClient::GetThreadStopInfo (lldb::tid_t tid, StringExtractorGDBRemote &response)
-{
- if (m_supports_qThreadStopInfo)
- {
- char packet[256];
- int packet_len = ::snprintf(packet, sizeof(packet), "qThreadStopInfo%" PRIx64, tid);
- assert (packet_len < (int)sizeof(packet));
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.IsUnsupportedResponse())
- m_supports_qThreadStopInfo = false;
- else if (response.IsNormalResponse())
- return true;
- else
- return false;
- }
- else
- {
- m_supports_qThreadStopInfo = false;
- }
+ // Check if the stub is known not to support this breakpoint type
+ if (!SupportsGDBStoppointPacket(type))
+ return UINT8_MAX;
+ // Construct the breakpoint packet
+ char packet[64];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "%c%i,%" PRIx64 ",%x",
+ insert ? 'Z' : 'z', type, addr, length);
+ // Check we haven't overwritten the end of the packet buffer
+ assert(packet_len + 1 < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ // Make sure the response is either "OK", "EXX" where XX are two hex digits,
+ // or "" (unsupported)
+ response.SetResponseValidatorToOKErrorNotSupported();
+ // Try to send the breakpoint packet, and check that it was correctly sent
+ if (SendPacketAndWaitForResponse(packet, response, true) ==
+ PacketResult::Success) {
+ // Receive and OK packet when the breakpoint successfully placed
+ if (response.IsOKResponse())
+ return 0;
+
+ // Error while setting breakpoint, send back specific error
+ if (response.IsErrorResponse())
+ return response.GetError();
+
+ // Empty packet informs us that breakpoint is not supported
+ if (response.IsUnsupportedResponse()) {
+ // Disable this breakpoint type since it is unsupported
+ switch (type) {
+ case eBreakpointSoftware:
+ m_supports_z0 = false;
+ break;
+ case eBreakpointHardware:
+ m_supports_z1 = false;
+ break;
+ case eWatchpointWrite:
+ m_supports_z2 = false;
+ break;
+ case eWatchpointRead:
+ m_supports_z3 = false;
+ break;
+ case eWatchpointReadWrite:
+ m_supports_z4 = false;
+ break;
+ case eStoppointInvalid:
+ return UINT8_MAX;
+ }
}
- return false;
+ }
+ // Signal generic failure
+ return UINT8_MAX;
}
+size_t GDBRemoteCommunicationClient::GetCurrentThreadIDs(
+ std::vector<lldb::tid_t> &thread_ids, bool &sequence_mutex_unavailable) {
+ thread_ids.clear();
-uint8_t
-GDBRemoteCommunicationClient::SendGDBStoppointTypePacket (GDBStoppointType type, bool insert, addr_t addr, uint32_t length)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf ("GDBRemoteCommunicationClient::%s() %s at addr = 0x%" PRIx64,
- __FUNCTION__, insert ? "add" : "remove", addr);
-
- // Check if the stub is known not to support this breakpoint type
- if (!SupportsGDBStoppointPacket(type))
- return UINT8_MAX;
- // Construct the breakpoint packet
- char packet[64];
- const int packet_len = ::snprintf (packet,
- sizeof(packet),
- "%c%i,%" PRIx64 ",%x",
- insert ? 'Z' : 'z',
- type,
- addr,
- length);
- // Check we haven't overwritten the end of the packet buffer
- assert (packet_len + 1 < (int)sizeof(packet));
+ Lock lock(*this, false);
+ if (lock) {
+ sequence_mutex_unavailable = false;
StringExtractorGDBRemote response;
- // Make sure the response is either "OK", "EXX" where XX are two hex digits, or "" (unsupported)
- response.SetResponseValidatorToOKErrorNotSupported();
- // Try to send the breakpoint packet, and check that it was correctly sent
- if (SendPacketAndWaitForResponse(packet, packet_len, response, true) == PacketResult::Success)
- {
- // Receive and OK packet when the breakpoint successfully placed
- if (response.IsOKResponse())
- return 0;
-
- // Error while setting breakpoint, send back specific error
- if (response.IsErrorResponse())
- return response.GetError();
-
- // Empty packet informs us that breakpoint is not supported
- if (response.IsUnsupportedResponse())
- {
- // Disable this breakpoint type since it is unsupported
- switch (type)
- {
- case eBreakpointSoftware: m_supports_z0 = false; break;
- case eBreakpointHardware: m_supports_z1 = false; break;
- case eWatchpointWrite: m_supports_z2 = false; break;
- case eWatchpointRead: m_supports_z3 = false; break;
- case eWatchpointReadWrite: m_supports_z4 = false; break;
- case eStoppointInvalid: return UINT8_MAX;
- }
- }
- }
- // Signal generic failure
- return UINT8_MAX;
-}
-
-size_t
-GDBRemoteCommunicationClient::GetCurrentThreadIDs (std::vector<lldb::tid_t> &thread_ids,
- bool &sequence_mutex_unavailable)
-{
- Mutex::Locker locker;
- thread_ids.clear();
-
- if (GetSequenceMutex (locker, "ProcessGDBRemote::UpdateThreadList() failed due to not getting the sequence mutex"))
- {
- sequence_mutex_unavailable = false;
- StringExtractorGDBRemote response;
-
- PacketResult packet_result;
- for (packet_result = SendPacketAndWaitForResponseNoLock ("qfThreadInfo", strlen("qfThreadInfo"), response);
- packet_result == PacketResult::Success && response.IsNormalResponse();
- packet_result = SendPacketAndWaitForResponseNoLock ("qsThreadInfo", strlen("qsThreadInfo"), response))
- {
- char ch = response.GetChar();
- if (ch == 'l')
- break;
- if (ch == 'm')
- {
- do
- {
- tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
-
- if (tid != LLDB_INVALID_THREAD_ID)
- {
- thread_ids.push_back (tid);
- }
- ch = response.GetChar(); // Skip the command separator
- } while (ch == ','); // Make sure we got a comma separator
- }
- }
- /*
- * Connected bare-iron target (like YAMON gdb-stub) may not have support for
- * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet could
- * be as simple as 'S05'. There is no packet which can give us pid and/or tid.
- * Assume pid=tid=1 in such cases.
- */
- if (response.IsUnsupportedResponse() && thread_ids.size() == 0 && IsConnected())
- {
- thread_ids.push_back (1);
- }
- }
- else
- {
-#if defined (LLDB_CONFIGURATION_DEBUG)
- // assert(!"ProcessGDBRemote::UpdateThreadList() failed due to not getting the sequence mutex");
-#else
- Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS | GDBR_LOG_PACKETS));
- if (log)
- log->Printf("error: failed to get packet sequence mutex, not sending packet 'qfThreadInfo'");
+ PacketResult packet_result;
+ for (packet_result =
+ SendPacketAndWaitForResponseNoLock("qfThreadInfo", response);
+ packet_result == PacketResult::Success && response.IsNormalResponse();
+ packet_result =
+ SendPacketAndWaitForResponseNoLock("qsThreadInfo", response)) {
+ char ch = response.GetChar();
+ if (ch == 'l')
+ break;
+ if (ch == 'm') {
+ do {
+ tid_t tid = response.GetHexMaxU64(false, LLDB_INVALID_THREAD_ID);
+
+ if (tid != LLDB_INVALID_THREAD_ID) {
+ thread_ids.push_back(tid);
+ }
+ ch = response.GetChar(); // Skip the command separator
+ } while (ch == ','); // Make sure we got a comma separator
+ }
+ }
+
+ /*
+ * Connected bare-iron target (like YAMON gdb-stub) may not have support for
+ * qProcessInfo, qC and qfThreadInfo packets. The reply from '?' packet
+ * could
+ * be as simple as 'S05'. There is no packet which can give us pid and/or
+ * tid.
+ * Assume pid=tid=1 in such cases.
+ */
+ if (response.IsUnsupportedResponse() && thread_ids.size() == 0 &&
+ IsConnected()) {
+ thread_ids.push_back(1);
+ }
+ } else {
+#if !defined(LLDB_CONFIGURATION_DEBUG)
+ Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_PROCESS |
+ GDBR_LOG_PACKETS));
+ if (log)
+ log->Printf("error: failed to get packet sequence mutex, not sending "
+ "packet 'qfThreadInfo'");
#endif
- sequence_mutex_unavailable = true;
- }
- return thread_ids.size();
+ sequence_mutex_unavailable = true;
+ }
+ return thread_ids.size();
}
-lldb::addr_t
-GDBRemoteCommunicationClient::GetShlibInfoAddr()
-{
- if (!IsRunning())
- {
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse("qShlibInfoAddr", ::strlen ("qShlibInfoAddr"), response, false) == PacketResult::Success)
- {
- if (response.IsNormalResponse())
- return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
- }
- }
+lldb::addr_t GDBRemoteCommunicationClient::GetShlibInfoAddr() {
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse("qShlibInfoAddr", response, false) !=
+ PacketResult::Success ||
+ !response.IsNormalResponse())
return LLDB_INVALID_ADDRESS;
-}
-
-lldb_private::Error
-GDBRemoteCommunicationClient::RunShellCommand(const char *command, // Shouldn't be NULL
- const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory
- int *status_ptr, // Pass NULL if you don't want the process exit status
- int *signo_ptr, // Pass NULL if you don't want the signal that caused the process to exit
- std::string *command_output, // Pass NULL if you don't want the command output
- uint32_t timeout_sec) // Timeout in seconds to wait for shell program to finish
-{
- lldb_private::StreamString stream;
- stream.PutCString("qPlatform_shell:");
- stream.PutBytesAsRawHex8(command, strlen(command));
- stream.PutChar(',');
- stream.PutHex32(timeout_sec);
- if (working_dir)
- {
- std::string path{working_dir.GetPath(false)};
- stream.PutChar(',');
- stream.PutCStringAsRawHex8(path.c_str());
- }
- const char *packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.GetChar() != 'F')
- return Error("malformed reply");
- if (response.GetChar() != ',')
- return Error("malformed reply");
- uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX);
- if (exitcode == UINT32_MAX)
- return Error("unable to run remote process");
- else if (status_ptr)
- *status_ptr = exitcode;
- if (response.GetChar() != ',')
- return Error("malformed reply");
- uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX);
- if (signo_ptr)
- *signo_ptr = signo;
- if (response.GetChar() != ',')
- return Error("malformed reply");
- std::string output;
- response.GetEscapedBinaryData(output);
- if (command_output)
- command_output->assign(output);
- return Error();
- }
- return Error("unable to send packet");
-}
-
-Error
-GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec,
- uint32_t file_permissions)
-{
- std::string path{file_spec.GetPath(false)};
- lldb_private::StreamString stream;
- stream.PutCString("qPlatform_mkdir:");
- stream.PutHex32(file_permissions);
+ return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
+}
+
+lldb_private::Error GDBRemoteCommunicationClient::RunShellCommand(
+ const char *command, // Shouldn't be NULL
+ const FileSpec &
+ working_dir, // Pass empty FileSpec to use the current working directory
+ int *status_ptr, // Pass NULL if you don't want the process exit status
+ int *signo_ptr, // Pass NULL if you don't want the signal that caused the
+ // process to exit
+ std::string
+ *command_output, // Pass NULL if you don't want the command output
+ uint32_t
+ timeout_sec) // Timeout in seconds to wait for shell program to finish
+{
+ lldb_private::StreamString stream;
+ stream.PutCString("qPlatform_shell:");
+ stream.PutBytesAsRawHex8(command, strlen(command));
+ stream.PutChar(',');
+ stream.PutHex32(timeout_sec);
+ if (working_dir) {
+ std::string path{working_dir.GetPath(false)};
stream.PutChar(',');
stream.PutCStringAsRawHex8(path.c_str());
- const char *packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
-
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) != PacketResult::Success)
- return Error("failed to send '%s' packet", packet);
-
+ }
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
if (response.GetChar() != 'F')
- return Error("invalid response to '%s' packet", packet);
-
- return Error(response.GetU32(UINT32_MAX), eErrorTypePOSIX);
-}
-
-Error
-GDBRemoteCommunicationClient::SetFilePermissions(const FileSpec &file_spec,
- uint32_t file_permissions)
-{
- std::string path{file_spec.GetPath(false)};
- lldb_private::StreamString stream;
- stream.PutCString("qPlatform_chmod:");
- stream.PutHex32(file_permissions);
- stream.PutChar(',');
- stream.PutCStringAsRawHex8(path.c_str());
- const char *packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
-
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) != PacketResult::Success)
- return Error("failed to send '%s' packet", packet);
-
- if (response.GetChar() != 'F')
- return Error("invalid response to '%s' packet", packet);
-
- return Error(response.GetU32(UINT32_MAX), eErrorTypePOSIX);
-}
-
-static uint64_t
-ParseHostIOPacketResponse (StringExtractorGDBRemote &response,
- uint64_t fail_result,
- Error &error)
-{
- response.SetFilePos(0);
- if (response.GetChar() != 'F')
- return fail_result;
- int32_t result = response.GetS32 (-2);
- if (result == -2)
- return fail_result;
- if (response.GetChar() == ',')
- {
- int result_errno = response.GetS32 (-2);
- if (result_errno != -2)
- error.SetError(result_errno, eErrorTypePOSIX);
- else
- error.SetError(-1, eErrorTypeGeneric);
- }
+ return Error("malformed reply");
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ uint32_t exitcode = response.GetHexMaxU32(false, UINT32_MAX);
+ if (exitcode == UINT32_MAX)
+ return Error("unable to run remote process");
+ else if (status_ptr)
+ *status_ptr = exitcode;
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ uint32_t signo = response.GetHexMaxU32(false, UINT32_MAX);
+ if (signo_ptr)
+ *signo_ptr = signo;
+ if (response.GetChar() != ',')
+ return Error("malformed reply");
+ std::string output;
+ response.GetEscapedBinaryData(output);
+ if (command_output)
+ command_output->assign(output);
+ return Error();
+ }
+ return Error("unable to send packet");
+}
+
+Error GDBRemoteCommunicationClient::MakeDirectory(const FileSpec &file_spec,
+ uint32_t file_permissions) {
+ std::string path{file_spec.GetPath(false)};
+ lldb_private::StreamString stream;
+ stream.PutCString("qPlatform_mkdir:");
+ stream.PutHex32(file_permissions);
+ stream.PutChar(',');
+ stream.PutCStringAsRawHex8(path.c_str());
+ llvm::StringRef packet = stream.GetString();
+ StringExtractorGDBRemote response;
+
+ if (SendPacketAndWaitForResponse(packet, response, false) !=
+ PacketResult::Success)
+ return Error("failed to send '%s' packet", packet.str().c_str());
+
+ if (response.GetChar() != 'F')
+ return Error("invalid response to '%s' packet", packet.str().c_str());
+
+ return Error(response.GetU32(UINT32_MAX), eErrorTypePOSIX);
+}
+
+Error GDBRemoteCommunicationClient::SetFilePermissions(
+ const FileSpec &file_spec, uint32_t file_permissions) {
+ std::string path{file_spec.GetPath(false)};
+ lldb_private::StreamString stream;
+ stream.PutCString("qPlatform_chmod:");
+ stream.PutHex32(file_permissions);
+ stream.PutChar(',');
+ stream.PutCStringAsRawHex8(path.c_str());
+ llvm::StringRef packet = stream.GetString();
+ StringExtractorGDBRemote response;
+
+ if (SendPacketAndWaitForResponse(packet, response, false) !=
+ PacketResult::Success)
+ return Error("failed to send '%s' packet", stream.GetData());
+
+ if (response.GetChar() != 'F')
+ return Error("invalid response to '%s' packet", stream.GetData());
+
+ return Error(response.GetU32(UINT32_MAX), eErrorTypePOSIX);
+}
+
+static uint64_t ParseHostIOPacketResponse(StringExtractorGDBRemote &response,
+ uint64_t fail_result, Error &error) {
+ response.SetFilePos(0);
+ if (response.GetChar() != 'F')
+ return fail_result;
+ int32_t result = response.GetS32(-2);
+ if (result == -2)
+ return fail_result;
+ if (response.GetChar() == ',') {
+ int result_errno = response.GetS32(-2);
+ if (result_errno != -2)
+ error.SetError(result_errno, eErrorTypePOSIX);
else
- error.Clear();
- return result;
+ error.SetError(-1, eErrorTypeGeneric);
+ } else
+ error.Clear();
+ return result;
}
lldb::user_id_t
-GDBRemoteCommunicationClient::OpenFile (const lldb_private::FileSpec& file_spec,
- uint32_t flags,
- mode_t mode,
- Error &error)
-{
- std::string path(file_spec.GetPath(false));
- lldb_private::StreamString stream;
- stream.PutCString("vFile:open:");
- if (path.empty())
- return UINT64_MAX;
- stream.PutCStringAsRawHex8(path.c_str());
- stream.PutChar(',');
- stream.PutHex32(flags);
- stream.PutChar(',');
- stream.PutHex32(mode);
- const char* packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- return ParseHostIOPacketResponse (response, UINT64_MAX, error);
- }
+GDBRemoteCommunicationClient::OpenFile(const lldb_private::FileSpec &file_spec,
+ uint32_t flags, mode_t mode,
+ Error &error) {
+ std::string path(file_spec.GetPath(false));
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:open:");
+ if (path.empty())
return UINT64_MAX;
-}
-
-bool
-GDBRemoteCommunicationClient::CloseFile (lldb::user_id_t fd,
- Error &error)
-{
- lldb_private::StreamString stream;
- stream.Printf("vFile:close:%i", (int)fd);
- const char* packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- return ParseHostIOPacketResponse (response, -1, error) == 0;
- }
- return false;
+ stream.PutCStringAsRawHex8(path.c_str());
+ stream.PutChar(',');
+ stream.PutHex32(flags);
+ stream.PutChar(',');
+ stream.PutHex32(mode);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ return ParseHostIOPacketResponse(response, UINT64_MAX, error);
+ }
+ return UINT64_MAX;
+}
+
+bool GDBRemoteCommunicationClient::CloseFile(lldb::user_id_t fd, Error &error) {
+ lldb_private::StreamString stream;
+ stream.Printf("vFile:close:%i", (int)fd);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ return ParseHostIOPacketResponse(response, -1, error) == 0;
+ }
+ return false;
}
// Extension of host I/O packets to get the file size.
-lldb::user_id_t
-GDBRemoteCommunicationClient::GetFileSize (const lldb_private::FileSpec& file_spec)
-{
- std::string path(file_spec.GetPath(false));
- lldb_private::StreamString stream;
- stream.PutCString("vFile:size:");
- stream.PutCStringAsRawHex8(path.c_str());
- const char* packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.GetChar() != 'F')
- return UINT64_MAX;
- uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
- return retcode;
- }
- return UINT64_MAX;
+lldb::user_id_t GDBRemoteCommunicationClient::GetFileSize(
+ const lldb_private::FileSpec &file_spec) {
+ std::string path(file_spec.GetPath(false));
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:size:");
+ stream.PutCStringAsRawHex8(path.c_str());
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.GetChar() != 'F')
+ return UINT64_MAX;
+ uint32_t retcode = response.GetHexMaxU64(false, UINT64_MAX);
+ return retcode;
+ }
+ return UINT64_MAX;
+}
+
+Error GDBRemoteCommunicationClient::GetFilePermissions(
+ const FileSpec &file_spec, uint32_t &file_permissions) {
+ std::string path{file_spec.GetPath(false)};
+ Error error;
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:mode:");
+ stream.PutCStringAsRawHex8(path.c_str());
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.GetChar() != 'F') {
+ error.SetErrorStringWithFormat("invalid response to '%s' packet",
+ stream.GetData());
+ } else {
+ const uint32_t mode = response.GetS32(-1);
+ if (static_cast<int32_t>(mode) == -1) {
+ if (response.GetChar() == ',') {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ else
+ error.SetErrorToGenericError();
+ } else
+ error.SetErrorToGenericError();
+ } else {
+ file_permissions = mode & (S_IRWXU | S_IRWXG | S_IRWXO);
+ }
+ }
+ } else {
+ error.SetErrorStringWithFormat("failed to send '%s' packet",
+ stream.GetData());
+ }
+ return error;
+}
+
+uint64_t GDBRemoteCommunicationClient::ReadFile(lldb::user_id_t fd,
+ uint64_t offset, void *dst,
+ uint64_t dst_len,
+ Error &error) {
+ lldb_private::StreamString stream;
+ stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len,
+ offset);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.GetChar() != 'F')
+ return 0;
+ uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
+ if (retcode == UINT32_MAX)
+ return retcode;
+ const char next = (response.Peek() ? *response.Peek() : 0);
+ if (next == ',')
+ return 0;
+ if (next == ';') {
+ response.GetChar(); // skip the semicolon
+ std::string buffer;
+ if (response.GetEscapedBinaryData(buffer)) {
+ const uint64_t data_to_write =
+ std::min<uint64_t>(dst_len, buffer.size());
+ if (data_to_write > 0)
+ memcpy(dst, &buffer[0], data_to_write);
+ return data_to_write;
+ }
+ }
+ }
+ return 0;
+}
+
+uint64_t GDBRemoteCommunicationClient::WriteFile(lldb::user_id_t fd,
+ uint64_t offset,
+ const void *src,
+ uint64_t src_len,
+ Error &error) {
+ lldb_private::StreamGDBRemote stream;
+ stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
+ stream.PutEscapedBytes(src, src_len);
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.GetChar() != 'F') {
+ error.SetErrorStringWithFormat("write file failed");
+ return 0;
+ }
+ uint64_t bytes_written = response.GetU64(UINT64_MAX);
+ if (bytes_written == UINT64_MAX) {
+ error.SetErrorToGenericError();
+ if (response.GetChar() == ',') {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ }
+ return 0;
+ }
+ return bytes_written;
+ } else {
+ error.SetErrorString("failed to send vFile:pwrite packet");
+ }
+ return 0;
+}
+
+Error GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src,
+ const FileSpec &dst) {
+ std::string src_path{src.GetPath(false)}, dst_path{dst.GetPath(false)};
+ Error error;
+ lldb_private::StreamGDBRemote stream;
+ stream.PutCString("vFile:symlink:");
+ // the unix symlink() command reverses its parameters where the dst if first,
+ // so we follow suit here
+ stream.PutCStringAsRawHex8(dst_path.c_str());
+ stream.PutChar(',');
+ stream.PutCStringAsRawHex8(src_path.c_str());
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.GetChar() == 'F') {
+ uint32_t result = response.GetU32(UINT32_MAX);
+ if (result != 0) {
+ error.SetErrorToGenericError();
+ if (response.GetChar() == ',') {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ }
+ }
+ } else {
+ // Should have returned with 'F<result>[,<errno>]'
+ error.SetErrorStringWithFormat("symlink failed");
+ }
+ } else {
+ error.SetErrorString("failed to send vFile:symlink packet");
+ }
+ return error;
+}
+
+Error GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec) {
+ std::string path{file_spec.GetPath(false)};
+ Error error;
+ lldb_private::StreamGDBRemote stream;
+ stream.PutCString("vFile:unlink:");
+ // the unix symlink() command reverses its parameters where the dst if first,
+ // so we follow suit here
+ stream.PutCStringAsRawHex8(path.c_str());
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.GetChar() == 'F') {
+ uint32_t result = response.GetU32(UINT32_MAX);
+ if (result != 0) {
+ error.SetErrorToGenericError();
+ if (response.GetChar() == ',') {
+ int response_errno = response.GetS32(-1);
+ if (response_errno > 0)
+ error.SetError(response_errno, lldb::eErrorTypePOSIX);
+ }
+ }
+ } else {
+ // Should have returned with 'F<result>[,<errno>]'
+ error.SetErrorStringWithFormat("unlink failed");
+ }
+ } else {
+ error.SetErrorString("failed to send vFile:unlink packet");
+ }
+ return error;
}
-Error
-GDBRemoteCommunicationClient::GetFilePermissions(const FileSpec &file_spec,
- uint32_t &file_permissions)
-{
- std::string path{file_spec.GetPath(false)};
- Error error;
- lldb_private::StreamString stream;
- stream.PutCString("vFile:mode:");
- stream.PutCStringAsRawHex8(path.c_str());
- const char* packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.GetChar() != 'F')
- {
- error.SetErrorStringWithFormat ("invalid response to '%s' packet", packet);
- }
- else
- {
- const uint32_t mode = response.GetS32(-1);
- if (static_cast<int32_t>(mode) == -1)
- {
- if (response.GetChar() == ',')
- {
- int response_errno = response.GetS32(-1);
- if (response_errno > 0)
- error.SetError(response_errno, lldb::eErrorTypePOSIX);
- else
- error.SetErrorToGenericError();
- }
- else
- error.SetErrorToGenericError();
- }
- else
- {
- file_permissions = mode & (S_IRWXU|S_IRWXG|S_IRWXO);
- }
- }
- }
- else
- {
- error.SetErrorStringWithFormat ("failed to send '%s' packet", packet);
- }
- return error;
-}
+// Extension of host I/O packets to get whether a file exists.
+bool GDBRemoteCommunicationClient::GetFileExists(
+ const lldb_private::FileSpec &file_spec) {
+ std::string path(file_spec.GetPath(false));
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:exists:");
+ stream.PutCStringAsRawHex8(path.c_str());
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.GetChar() != 'F')
+ return false;
+ if (response.GetChar() != ',')
+ return false;
+ bool retcode = (response.GetChar() != '0');
+ return retcode;
+ }
+ return false;
+}
+
+bool GDBRemoteCommunicationClient::CalculateMD5(
+ const lldb_private::FileSpec &file_spec, uint64_t &high, uint64_t &low) {
+ std::string path(file_spec.GetPath(false));
+ lldb_private::StreamString stream;
+ stream.PutCString("vFile:MD5:");
+ stream.PutCStringAsRawHex8(path.c_str());
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(stream.GetString(), response, false) ==
+ PacketResult::Success) {
+ if (response.GetChar() != 'F')
+ return false;
+ if (response.GetChar() != ',')
+ return false;
+ if (response.Peek() && *response.Peek() == 'x')
+ return false;
+ low = response.GetHexMaxU64(false, UINT64_MAX);
+ high = response.GetHexMaxU64(false, UINT64_MAX);
+ return true;
+ }
+ return false;
+}
+
+bool GDBRemoteCommunicationClient::AvoidGPackets(ProcessGDBRemote *process) {
+ // Some targets have issues with g/G packets and we need to avoid using them
+ if (m_avoid_g_packets == eLazyBoolCalculate) {
+ if (process) {
+ m_avoid_g_packets = eLazyBoolNo;
+ const ArchSpec &arch = process->GetTarget().GetArchitecture();
+ if (arch.IsValid() &&
+ arch.GetTriple().getVendor() == llvm::Triple::Apple &&
+ arch.GetTriple().getOS() == llvm::Triple::IOS &&
+ arch.GetTriple().getArch() == llvm::Triple::aarch64) {
+ m_avoid_g_packets = eLazyBoolYes;
+ uint32_t gdb_server_version = GetGDBServerProgramVersion();
+ if (gdb_server_version != 0) {
+ const char *gdb_server_name = GetGDBServerProgramName();
+ if (gdb_server_name && strcmp(gdb_server_name, "debugserver") == 0) {
+ if (gdb_server_version >= 310)
+ m_avoid_g_packets = eLazyBoolNo;
+ }
+ }
+ }
+ }
+ }
+ return m_avoid_g_packets == eLazyBoolYes;
+}
+
+DataBufferSP GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid,
+ uint32_t reg) {
+ StreamString payload;
+ payload.Printf("p%x", reg);
+ StringExtractorGDBRemote response;
+ if (SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response, false) != PacketResult::Success ||
+ !response.IsNormalResponse())
+ return nullptr;
+
+ DataBufferSP buffer_sp(
+ new DataBufferHeap(response.GetStringRef().size() / 2, 0));
+ response.GetHexBytes(buffer_sp->GetData(), '\xcc');
+ return buffer_sp;
+}
+
+DataBufferSP GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid) {
+ StreamString payload;
+ payload.PutChar('g');
+ StringExtractorGDBRemote response;
+ if (SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response, false) != PacketResult::Success ||
+ !response.IsNormalResponse())
+ return nullptr;
+
+ DataBufferSP buffer_sp(
+ new DataBufferHeap(response.GetStringRef().size() / 2, 0));
+ response.GetHexBytes(buffer_sp->GetData(), '\xcc');
+ return buffer_sp;
+}
+
+bool GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid,
+ uint32_t reg_num,
+ llvm::ArrayRef<uint8_t> data) {
+ StreamString payload;
+ payload.Printf("P%x=", reg_num);
+ payload.PutBytesAsRawHex8(data.data(), data.size(),
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
+ StringExtractorGDBRemote response;
+ return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
+ response, false) ==
+ PacketResult::Success &&
+ response.IsOKResponse();
+}
+
+bool GDBRemoteCommunicationClient::WriteAllRegisters(
+ lldb::tid_t tid, llvm::ArrayRef<uint8_t> data) {
+ StreamString payload;
+ payload.PutChar('G');
+ payload.PutBytesAsRawHex8(data.data(), data.size(),
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
+ StringExtractorGDBRemote response;
+ return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload),
+ response, false) ==
+ PacketResult::Success &&
+ response.IsOKResponse();
+}
+
+bool GDBRemoteCommunicationClient::SaveRegisterState(lldb::tid_t tid,
+ uint32_t &save_id) {
+ save_id = 0; // Set to invalid save ID
+ if (m_supports_QSaveRegisterState == eLazyBoolNo)
+ return false;
-uint64_t
-GDBRemoteCommunicationClient::ReadFile (lldb::user_id_t fd,
- uint64_t offset,
- void *dst,
- uint64_t dst_len,
- Error &error)
-{
- lldb_private::StreamString stream;
- stream.Printf("vFile:pread:%i,%" PRId64 ",%" PRId64, (int)fd, dst_len, offset);
- const char* packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.GetChar() != 'F')
- return 0;
- uint32_t retcode = response.GetHexMaxU32(false, UINT32_MAX);
- if (retcode == UINT32_MAX)
- return retcode;
- const char next = (response.Peek() ? *response.Peek() : 0);
- if (next == ',')
- return 0;
- if (next == ';')
- {
- response.GetChar(); // skip the semicolon
- std::string buffer;
- if (response.GetEscapedBinaryData(buffer))
- {
- const uint64_t data_to_write = std::min<uint64_t>(dst_len, buffer.size());
- if (data_to_write > 0)
- memcpy(dst, &buffer[0], data_to_write);
- return data_to_write;
- }
- }
- }
- return 0;
-}
+ m_supports_QSaveRegisterState = eLazyBoolYes;
+ StreamString payload;
+ payload.PutCString("QSaveRegisterState");
+ StringExtractorGDBRemote response;
+ if (SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response, false) != PacketResult::Success)
+ return false;
-uint64_t
-GDBRemoteCommunicationClient::WriteFile (lldb::user_id_t fd,
- uint64_t offset,
- const void* src,
- uint64_t src_len,
- Error &error)
-{
- lldb_private::StreamGDBRemote stream;
- stream.Printf("vFile:pwrite:%i,%" PRId64 ",", (int)fd, offset);
- stream.PutEscapedBytes(src, src_len);
- const char* packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.GetChar() != 'F')
- {
- error.SetErrorStringWithFormat("write file failed");
- return 0;
- }
- uint64_t bytes_written = response.GetU64(UINT64_MAX);
- if (bytes_written == UINT64_MAX)
- {
- error.SetErrorToGenericError();
- if (response.GetChar() == ',')
- {
- int response_errno = response.GetS32(-1);
- if (response_errno > 0)
- error.SetError(response_errno, lldb::eErrorTypePOSIX);
- }
- return 0;
- }
- return bytes_written;
- }
- else
- {
- error.SetErrorString ("failed to send vFile:pwrite packet");
- }
- return 0;
-}
+ if (response.IsUnsupportedResponse())
+ m_supports_QSaveRegisterState = eLazyBoolNo;
-Error
-GDBRemoteCommunicationClient::CreateSymlink(const FileSpec &src, const FileSpec &dst)
-{
- std::string src_path{src.GetPath(false)},
- dst_path{dst.GetPath(false)};
- Error error;
- lldb_private::StreamGDBRemote stream;
- stream.PutCString("vFile:symlink:");
- // the unix symlink() command reverses its parameters where the dst if first,
- // so we follow suit here
- stream.PutCStringAsRawHex8(dst_path.c_str());
- stream.PutChar(',');
- stream.PutCStringAsRawHex8(src_path.c_str());
- const char* packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.GetChar() == 'F')
- {
- uint32_t result = response.GetU32(UINT32_MAX);
- if (result != 0)
- {
- error.SetErrorToGenericError();
- if (response.GetChar() == ',')
- {
- int response_errno = response.GetS32(-1);
- if (response_errno > 0)
- error.SetError(response_errno, lldb::eErrorTypePOSIX);
- }
- }
- }
- else
- {
- // Should have returned with 'F<result>[,<errno>]'
- error.SetErrorStringWithFormat("symlink failed");
- }
- }
- else
- {
- error.SetErrorString ("failed to send vFile:symlink packet");
- }
- return error;
-}
+ const uint32_t response_save_id = response.GetU32(0);
+ if (response_save_id == 0)
+ return false;
-Error
-GDBRemoteCommunicationClient::Unlink(const FileSpec &file_spec)
-{
- std::string path{file_spec.GetPath(false)};
- Error error;
- lldb_private::StreamGDBRemote stream;
- stream.PutCString("vFile:unlink:");
- // the unix symlink() command reverses its parameters where the dst if first,
- // so we follow suit here
- stream.PutCStringAsRawHex8(path.c_str());
- const char* packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.GetChar() == 'F')
- {
- uint32_t result = response.GetU32(UINT32_MAX);
- if (result != 0)
- {
- error.SetErrorToGenericError();
- if (response.GetChar() == ',')
- {
- int response_errno = response.GetS32(-1);
- if (response_errno > 0)
- error.SetError(response_errno, lldb::eErrorTypePOSIX);
- }
- }
- }
- else
- {
- // Should have returned with 'F<result>[,<errno>]'
- error.SetErrorStringWithFormat("unlink failed");
- }
- }
- else
- {
- error.SetErrorString ("failed to send vFile:unlink packet");
- }
- return error;
+ save_id = response_save_id;
+ return true;
}
-// Extension of host I/O packets to get whether a file exists.
-bool
-GDBRemoteCommunicationClient::GetFileExists (const lldb_private::FileSpec& file_spec)
-{
- std::string path(file_spec.GetPath(false));
- lldb_private::StreamString stream;
- stream.PutCString("vFile:exists:");
- stream.PutCStringAsRawHex8(path.c_str());
- const char* packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.GetChar() != 'F')
- return false;
- if (response.GetChar() != ',')
- return false;
- bool retcode = (response.GetChar() != '0');
- return retcode;
- }
+bool GDBRemoteCommunicationClient::RestoreRegisterState(lldb::tid_t tid,
+ uint32_t save_id) {
+ // We use the "m_supports_QSaveRegisterState" variable here because the
+ // QSaveRegisterState and QRestoreRegisterState packets must both be supported
+ // in
+ // order to be useful
+ if (m_supports_QSaveRegisterState == eLazyBoolNo)
return false;
-}
-bool
-GDBRemoteCommunicationClient::CalculateMD5 (const lldb_private::FileSpec& file_spec,
- uint64_t &high,
- uint64_t &low)
-{
- std::string path(file_spec.GetPath(false));
- lldb_private::StreamString stream;
- stream.PutCString("vFile:MD5:");
- stream.PutCStringAsRawHex8(path.c_str());
- const char* packet = stream.GetData();
- int packet_len = stream.GetSize();
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse(packet, packet_len, response, false) == PacketResult::Success)
- {
- if (response.GetChar() != 'F')
- return false;
- if (response.GetChar() != ',')
- return false;
- if (response.Peek() && *response.Peek() == 'x')
- return false;
- low = response.GetHexMaxU64(false, UINT64_MAX);
- high = response.GetHexMaxU64(false, UINT64_MAX);
- return true;
- }
+ StreamString payload;
+ payload.Printf("QRestoreRegisterState:%u", save_id);
+ StringExtractorGDBRemote response;
+ if (SendThreadSpecificPacketAndWaitForResponse(
+ tid, std::move(payload), response, false) != PacketResult::Success)
return false;
-}
-bool
-GDBRemoteCommunicationClient::AvoidGPackets (ProcessGDBRemote *process)
-{
- // Some targets have issues with g/G packets and we need to avoid using them
- if (m_avoid_g_packets == eLazyBoolCalculate)
- {
- if (process)
- {
- m_avoid_g_packets = eLazyBoolNo;
- const ArchSpec &arch = process->GetTarget().GetArchitecture();
- if (arch.IsValid()
- && arch.GetTriple().getVendor() == llvm::Triple::Apple
- && arch.GetTriple().getOS() == llvm::Triple::IOS
- && arch.GetTriple().getArch() == llvm::Triple::aarch64)
- {
- m_avoid_g_packets = eLazyBoolYes;
- uint32_t gdb_server_version = GetGDBServerProgramVersion();
- if (gdb_server_version != 0)
- {
- const char *gdb_server_name = GetGDBServerProgramName();
- if (gdb_server_name && strcmp(gdb_server_name, "debugserver") == 0)
- {
- if (gdb_server_version >= 310)
- m_avoid_g_packets = eLazyBoolNo;
- }
- }
- }
- }
- }
- return m_avoid_g_packets == eLazyBoolYes;
+ if (response.IsOKResponse())
+ return true;
+
+ if (response.IsUnsupportedResponse())
+ m_supports_QSaveRegisterState = eLazyBoolNo;
+ return false;
}
-bool
-GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, uint32_t reg, StringExtractorGDBRemote &response)
-{
- Mutex::Locker locker;
- if (GetSequenceMutex (locker, "Didn't get sequence mutex for p packet."))
- {
- const bool thread_suffix_supported = GetThreadSuffixSupported();
-
- if (thread_suffix_supported || SetCurrentThread(tid))
- {
- char packet[64];
- int packet_len = 0;
- if (thread_suffix_supported)
- packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4" PRIx64 ";", reg, tid);
- else
- packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
- assert (packet_len < ((int)sizeof(packet) - 1));
- return SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success;
- }
- }
+bool GDBRemoteCommunicationClient::SyncThreadState(lldb::tid_t tid) {
+ if (!GetSyncThreadStateSupported())
return false;
+ StreamString packet;
+ StringExtractorGDBRemote response;
+ packet.Printf("QSyncThreadState:%4.4" PRIx64 ";", tid);
+ return SendPacketAndWaitForResponse(packet.GetString(), response, false) ==
+ GDBRemoteCommunication::PacketResult::Success &&
+ response.IsOKResponse();
}
+bool GDBRemoteCommunicationClient::GetModuleInfo(
+ const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec,
+ ModuleSpec &module_spec) {
+ if (!m_supports_qModuleInfo)
+ return false;
-bool
-GDBRemoteCommunicationClient::ReadAllRegisters (lldb::tid_t tid, StringExtractorGDBRemote &response)
-{
- Mutex::Locker locker;
- if (GetSequenceMutex (locker, "Didn't get sequence mutex for g packet."))
- {
- const bool thread_suffix_supported = GetThreadSuffixSupported();
-
- if (thread_suffix_supported || SetCurrentThread(tid))
- {
- char packet[64];
- int packet_len = 0;
- // Get all registers in one packet
- if (thread_suffix_supported)
- packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64 ";", tid);
- else
- packet_len = ::snprintf (packet, sizeof(packet), "g");
- assert (packet_len < ((int)sizeof(packet) - 1));
- return SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success;
- }
- }
+ std::string module_path = module_file_spec.GetPath(false);
+ if (module_path.empty())
return false;
-}
-bool
-GDBRemoteCommunicationClient::SaveRegisterState (lldb::tid_t tid, uint32_t &save_id)
-{
- save_id = 0; // Set to invalid save ID
- if (m_supports_QSaveRegisterState == eLazyBoolNo)
- return false;
-
- m_supports_QSaveRegisterState = eLazyBoolYes;
- Mutex::Locker locker;
- if (GetSequenceMutex (locker, "Didn't get sequence mutex for QSaveRegisterState."))
- {
- const bool thread_suffix_supported = GetThreadSuffixSupported();
- if (thread_suffix_supported || SetCurrentThread(tid))
- {
- char packet[256];
- if (thread_suffix_supported)
- ::snprintf (packet, sizeof(packet), "QSaveRegisterState;thread:%4.4" PRIx64 ";", tid);
- else
- ::snprintf(packet, sizeof(packet), "QSaveRegisterState");
-
- StringExtractorGDBRemote response;
-
- if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
- {
- if (response.IsUnsupportedResponse())
- {
- // This packet isn't supported, don't try calling it again
- m_supports_QSaveRegisterState = eLazyBoolNo;
- }
-
- const uint32_t response_save_id = response.GetU32(0);
- if (response_save_id != 0)
- {
- save_id = response_save_id;
- return true;
- }
- }
- }
- }
+
+ StreamString packet;
+ packet.PutCString("qModuleInfo:");
+ packet.PutCStringAsRawHex8(module_path.c_str());
+ packet.PutCString(";");
+ const auto &triple = arch_spec.GetTriple().getTriple();
+ packet.PutCStringAsRawHex8(triple.c_str());
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(packet.GetString(), response, false) !=
+ PacketResult::Success)
return false;
-}
-bool
-GDBRemoteCommunicationClient::RestoreRegisterState (lldb::tid_t tid, uint32_t save_id)
-{
- // We use the "m_supports_QSaveRegisterState" variable here because the
- // QSaveRegisterState and QRestoreRegisterState packets must both be supported in
- // order to be useful
- if (m_supports_QSaveRegisterState == eLazyBoolNo)
- return false;
-
- Mutex::Locker locker;
- if (GetSequenceMutex (locker, "Didn't get sequence mutex for QRestoreRegisterState."))
- {
- const bool thread_suffix_supported = GetThreadSuffixSupported();
- if (thread_suffix_supported || SetCurrentThread(tid))
- {
- char packet[256];
- if (thread_suffix_supported)
- ::snprintf (packet, sizeof(packet), "QRestoreRegisterState:%u;thread:%4.4" PRIx64 ";", save_id, tid);
- else
- ::snprintf (packet, sizeof(packet), "QRestoreRegisterState:%u" PRIx64 ";", save_id);
-
- StringExtractorGDBRemote response;
-
- if (SendPacketAndWaitForResponse(packet, response, false) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- {
- return true;
- }
- else if (response.IsUnsupportedResponse())
- {
- // This packet isn't supported, don't try calling this packet or
- // QSaveRegisterState again...
- m_supports_QSaveRegisterState = eLazyBoolNo;
- }
- }
- }
- }
+ if (response.IsErrorResponse())
return false;
-}
-bool
-GDBRemoteCommunicationClient::GetModuleInfo (const FileSpec& module_file_spec,
- const lldb_private::ArchSpec& arch_spec,
- ModuleSpec &module_spec)
-{
- if (!m_supports_qModuleInfo)
- return false;
+ if (response.IsUnsupportedResponse()) {
+ m_supports_qModuleInfo = false;
+ return false;
+ }
+
+ llvm::StringRef name;
+ llvm::StringRef value;
+
+ module_spec.Clear();
+ module_spec.GetFileSpec() = module_file_spec;
+
+ while (response.GetNameColonValue(name, value)) {
+ if (name == "uuid" || name == "md5") {
+ StringExtractor extractor(value);
+ std::string uuid;
+ extractor.GetHexByteString(uuid);
+ module_spec.GetUUID().SetFromCString(uuid.c_str(), uuid.size() / 2);
+ } else if (name == "triple") {
+ StringExtractor extractor(value);
+ std::string triple;
+ extractor.GetHexByteString(triple);
+ module_spec.GetArchitecture().SetTriple(triple.c_str());
+ } else if (name == "file_offset") {
+ uint64_t ival = 0;
+ if (!value.getAsInteger(16, ival))
+ module_spec.SetObjectOffset(ival);
+ } else if (name == "file_size") {
+ uint64_t ival = 0;
+ if (!value.getAsInteger(16, ival))
+ module_spec.SetObjectSize(ival);
+ } else if (name == "file_path") {
+ StringExtractor extractor(value);
+ std::string path;
+ extractor.GetHexByteString(path);
+ module_spec.GetFileSpec() = FileSpec(path, false, arch_spec);
+ }
+ }
+
+ return true;
+}
+
+static llvm::Optional<ModuleSpec>
+ParseModuleSpec(StructuredData::Dictionary *dict) {
+ ModuleSpec result;
+ if (!dict)
+ return llvm::None;
+
+ std::string string;
+ uint64_t integer;
+
+ if (!dict->GetValueForKeyAsString("uuid", string))
+ return llvm::None;
+ result.GetUUID().SetFromCString(string.c_str(), string.size());
+
+ if (!dict->GetValueForKeyAsInteger("file_offset", integer))
+ return llvm::None;
+ result.SetObjectOffset(integer);
+
+ if (!dict->GetValueForKeyAsInteger("file_size", integer))
+ return llvm::None;
+ result.SetObjectSize(integer);
+
+ if (!dict->GetValueForKeyAsString("triple", string))
+ return llvm::None;
+ result.GetArchitecture().SetTriple(string.c_str());
+
+ if (!dict->GetValueForKeyAsString("file_path", string))
+ return llvm::None;
+ result.GetFileSpec() = FileSpec(string, false, result.GetArchitecture());
+
+ return result;
+}
+
+llvm::Optional<std::vector<ModuleSpec>>
+GDBRemoteCommunicationClient::GetModulesInfo(
+ llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) {
+ if (!m_supports_jModulesInfo)
+ return llvm::None;
+
+ JSONArray::SP module_array_sp = std::make_shared<JSONArray>();
+ for (const FileSpec &module_file_spec : module_file_specs) {
+ JSONObject::SP module_sp = std::make_shared<JSONObject>();
+ module_array_sp->AppendObject(module_sp);
+ module_sp->SetObject(
+ "file", std::make_shared<JSONString>(module_file_spec.GetPath(false)));
+ module_sp->SetObject("triple",
+ std::make_shared<JSONString>(triple.getTriple()));
+ }
+ StreamString unescaped_payload;
+ unescaped_payload.PutCString("jModulesInfo:");
+ module_array_sp->Write(unescaped_payload);
+ StreamGDBRemote payload;
+ payload.PutEscapedBytes(unescaped_payload.GetString().data(),
+ unescaped_payload.GetSize());
+
+ StringExtractorGDBRemote response;
+ if (SendPacketAndWaitForResponse(payload.GetString(), response, false) !=
+ PacketResult::Success ||
+ response.IsErrorResponse())
+ return llvm::None;
+
+ if (response.IsUnsupportedResponse()) {
+ m_supports_jModulesInfo = false;
+ return llvm::None;
+ }
+
+ StructuredData::ObjectSP response_object_sp =
+ StructuredData::ParseJSON(response.GetStringRef());
+ if (!response_object_sp)
+ return llvm::None;
+
+ StructuredData::Array *response_array = response_object_sp->GetAsArray();
+ if (!response_array)
+ return llvm::None;
+
+ std::vector<ModuleSpec> result;
+ for (size_t i = 0; i < response_array->GetSize(); ++i) {
+ if (llvm::Optional<ModuleSpec> module_spec = ParseModuleSpec(
+ response_array->GetItemAtIndex(i)->GetAsDictionary()))
+ result.push_back(*module_spec);
+ }
+
+ return result;
+}
- std::string module_path = module_file_spec.GetPath (false);
- if (module_path.empty ())
- return false;
+// query the target remote for extended information using the qXfer packet
+//
+// example: object='features', annex='target.xml', out=<xml output>
+// return: 'true' on success
+// 'false' on failure (err set)
+bool GDBRemoteCommunicationClient::ReadExtFeature(
+ const lldb_private::ConstString object,
+ const lldb_private::ConstString annex, std::string &out,
+ lldb_private::Error &err) {
- StreamString packet;
- packet.PutCString("qModuleInfo:");
- packet.PutCStringAsRawHex8(module_path.c_str());
- packet.PutCString(";");
- const auto& triple = arch_spec.GetTriple().getTriple();
- packet.PutCStringAsRawHex8(triple.c_str());
+ std::stringstream output;
+ StringExtractorGDBRemote chunk;
- StringExtractorGDBRemote response;
- if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false) != PacketResult::Success)
- return false;
+ uint64_t size = GetRemoteMaxPacketSize();
+ if (size == 0)
+ size = 0x1000;
+ size = size - 1; // Leave space for the 'm' or 'l' character in the response
+ int offset = 0;
+ bool active = true;
- if (response.IsErrorResponse ())
- return false;
+ // loop until all data has been read
+ while (active) {
- if (response.IsUnsupportedResponse ())
- {
- m_supports_qModuleInfo = false;
- return false;
- }
+ // send query extended feature packet
+ std::stringstream packet;
+ packet << "qXfer:" << object.AsCString("")
+ << ":read:" << annex.AsCString("") << ":" << std::hex << offset
+ << "," << std::hex << size;
- std::string name;
- std::string value;
- bool success;
- StringExtractor extractor;
+ GDBRemoteCommunication::PacketResult res =
+ SendPacketAndWaitForResponse(packet.str(), chunk, false);
- module_spec.Clear ();
- module_spec.GetFileSpec () = module_file_spec;
-
- while (response.GetNameColonValue (name, value))
- {
- if (name == "uuid" || name == "md5")
- {
- extractor.GetStringRef ().swap (value);
- extractor.SetFilePos (0);
- extractor.GetHexByteString (value);
- module_spec.GetUUID().SetFromCString (value.c_str(), value.size() / 2);
- }
- else if (name == "triple")
- {
- extractor.GetStringRef ().swap (value);
- extractor.SetFilePos (0);
- extractor.GetHexByteString (value);
- module_spec.GetArchitecture().SetTriple (value.c_str ());
- }
- else if (name == "file_offset")
- {
- const auto ival = StringConvert::ToUInt64 (value.c_str (), 0, 16, &success);
- if (success)
- module_spec.SetObjectOffset (ival);
- }
- else if (name == "file_size")
- {
- const auto ival = StringConvert::ToUInt64 (value.c_str (), 0, 16, &success);
- if (success)
- module_spec.SetObjectSize (ival);
- }
- else if (name == "file_path")
- {
- extractor.GetStringRef ().swap (value);
- extractor.SetFilePos (0);
- extractor.GetHexByteString (value);
- module_spec.GetFileSpec() = FileSpec(value.c_str(), false, arch_spec);
- }
+ if (res != GDBRemoteCommunication::PacketResult::Success) {
+ err.SetErrorString("Error sending $qXfer packet");
+ return false;
}
- return true;
-}
+ const std::string &str = chunk.GetStringRef();
+ if (str.length() == 0) {
+ // should have some data in chunk
+ err.SetErrorString("Empty response from $qXfer packet");
+ return false;
+ }
-// query the target remote for extended information using the qXfer packet
-//
-// example: object='features', annex='target.xml', out=<xml output>
-// return: 'true' on success
-// 'false' on failure (err set)
-bool
-GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString object,
- const lldb_private::ConstString annex,
- std::string & out,
- lldb_private::Error & err) {
-
- std::stringstream output;
- StringExtractorGDBRemote chunk;
-
- uint64_t size = GetRemoteMaxPacketSize();
- if (size == 0)
- size = 0x1000;
- size = size - 1; // Leave space for the 'm' or 'l' character in the response
- int offset = 0;
- bool active = true;
-
- // loop until all data has been read
- while ( active ) {
-
- // send query extended feature packet
- std::stringstream packet;
- packet << "qXfer:"
- << object.AsCString("") << ":read:"
- << annex.AsCString("") << ":"
- << std::hex << offset << ","
- << std::hex << size;
-
- GDBRemoteCommunication::PacketResult res =
- SendPacketAndWaitForResponse( packet.str().c_str(),
- chunk,
- false );
-
- if ( res != GDBRemoteCommunication::PacketResult::Success ) {
- err.SetErrorString( "Error sending $qXfer packet" );
- return false;
- }
+ // check packet code
+ switch (str[0]) {
+ // last chunk
+ case ('l'):
+ active = false;
+ LLVM_FALLTHROUGH;
- const std::string & str = chunk.GetStringRef( );
- if ( str.length() == 0 ) {
- // should have some data in chunk
- err.SetErrorString( "Empty response from $qXfer packet" );
- return false;
- }
+ // more chunks
+ case ('m'):
+ if (str.length() > 1)
+ output << &str[1];
+ offset += size;
+ break;
- // check packet code
- switch ( str[0] ) {
- // last chunk
- case ( 'l' ):
- active = false;
- LLVM_FALLTHROUGH;
-
- // more chunks
- case ( 'm' ) :
- if ( str.length() > 1 )
- output << &str[1];
- offset += size;
- break;
-
- // unknown chunk
- default:
- err.SetErrorString( "Invalid continuation code from $qXfer packet" );
- return false;
- }
+ // unknown chunk
+ default:
+ err.SetErrorString("Invalid continuation code from $qXfer packet");
+ return false;
}
+ }
- out = output.str( );
- err.Success( );
- return true;
+ out = output.str();
+ err.Success();
+ return true;
}
// Notify the target that gdb is prepared to serve symbol lookup requests.
// packet: "qSymbol::"
// reply:
// OK The target does not need to look up any (more) symbols.
-// qSymbol:<sym_name> The target requests the value of symbol sym_name (hex encoded).
-// LLDB may provide the value by sending another qSymbol packet
+// qSymbol:<sym_name> The target requests the value of symbol sym_name (hex
+// encoded).
+// LLDB may provide the value by sending another qSymbol
+// packet
// in the form of"qSymbol:<sym_value>:<sym_name>".
//
// Three examples:
//
// lldb sends: qSymbol::
// lldb receives: OK
-// Remote gdb stub does not need to know the addresses of any symbols, lldb does not
+// Remote gdb stub does not need to know the addresses of any symbols, lldb
+// does not
// need to ask again in this session.
//
// lldb sends: qSymbol::
// lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
// lldb sends: qSymbol::64697370617463685f71756575655f6f666673657473
// lldb receives: OK
-// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb does not know
-// the address at this time. lldb needs to send qSymbol:: again when it has more
+// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb does
+// not know
+// the address at this time. lldb needs to send qSymbol:: again when it has
+// more
// solibs loaded.
//
// lldb sends: qSymbol::
// lldb receives: qSymbol:64697370617463685f71756575655f6f666673657473
// lldb sends: qSymbol:2bc97554:64697370617463685f71756575655f6f666673657473
// lldb receives: OK
-// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb says that it
-// is at address 0x2bc97554. Remote gdb stub sends 'OK' indicating that it does not
+// Remote gdb stub asks for address of 'dispatch_queue_offsets'. lldb says
+// that it
+// is at address 0x2bc97554. Remote gdb stub sends 'OK' indicating that it
+// does not
// need any more symbols. lldb does not need to ask again in this session.
-void
-GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process)
-{
- // Set to true once we've resolved a symbol to an address for the remote stub.
- // If we get an 'OK' response after this, the remote stub doesn't need any more
- // symbols and we can stop asking.
- bool symbol_response_provided = false;
-
- // Is this the inital qSymbol:: packet?
- bool first_qsymbol_query = true;
-
- if (m_supports_qSymbol && m_qSymbol_requests_done == false)
- {
- Mutex::Locker locker;
- if (GetSequenceMutex(locker, "GDBRemoteCommunicationClient::ServeSymbolLookups() failed due to not getting the sequence mutex"))
- {
- StreamString packet;
- packet.PutCString ("qSymbol::");
- StringExtractorGDBRemote response;
- while (SendPacketAndWaitForResponseNoLock(packet.GetData(), packet.GetSize(), response) == PacketResult::Success)
- {
- if (response.IsOKResponse())
- {
- if (symbol_response_provided || first_qsymbol_query)
- {
- m_qSymbol_requests_done = true;
- }
-
- // We are done serving symbols requests
- return;
- }
- first_qsymbol_query = false;
+void GDBRemoteCommunicationClient::ServeSymbolLookups(
+ lldb_private::Process *process) {
+ // Set to true once we've resolved a symbol to an address for the remote stub.
+ // If we get an 'OK' response after this, the remote stub doesn't need any
+ // more
+ // symbols and we can stop asking.
+ bool symbol_response_provided = false;
+
+ // Is this the initial qSymbol:: packet?
+ bool first_qsymbol_query = true;
+
+ if (m_supports_qSymbol && m_qSymbol_requests_done == false) {
+ Lock lock(*this, false);
+ if (lock) {
+ StreamString packet;
+ packet.PutCString("qSymbol::");
+ StringExtractorGDBRemote response;
+ while (SendPacketAndWaitForResponseNoLock(packet.GetString(), response) ==
+ PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ if (symbol_response_provided || first_qsymbol_query) {
+ m_qSymbol_requests_done = true;
+ }
+
+ // We are done serving symbols requests
+ return;
+ }
+ first_qsymbol_query = false;
+
+ if (response.IsUnsupportedResponse()) {
+ // qSymbol is not supported by the current GDB server we are connected
+ // to
+ m_supports_qSymbol = false;
+ return;
+ } else {
+ llvm::StringRef response_str(response.GetStringRef());
+ if (response_str.startswith("qSymbol:")) {
+ response.SetFilePos(strlen("qSymbol:"));
+ std::string symbol_name;
+ if (response.GetHexByteString(symbol_name)) {
+ if (symbol_name.empty())
+ return;
+
+ addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
+ lldb_private::SymbolContextList sc_list;
+ if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(
+ ConstString(symbol_name), eSymbolTypeAny, sc_list)) {
+ const size_t num_scs = sc_list.GetSize();
+ for (size_t sc_idx = 0;
+ sc_idx < num_scs &&
+ symbol_load_addr == LLDB_INVALID_ADDRESS;
+ ++sc_idx) {
+ SymbolContext sc;
+ if (sc_list.GetContextAtIndex(sc_idx, sc)) {
+ if (sc.symbol) {
+ switch (sc.symbol->GetType()) {
+ case eSymbolTypeInvalid:
+ case eSymbolTypeAbsolute:
+ case eSymbolTypeUndefined:
+ case eSymbolTypeSourceFile:
+ case eSymbolTypeHeaderFile:
+ case eSymbolTypeObjectFile:
+ case eSymbolTypeCommonBlock:
+ case eSymbolTypeBlock:
+ case eSymbolTypeLocal:
+ case eSymbolTypeParam:
+ case eSymbolTypeVariable:
+ case eSymbolTypeVariableType:
+ case eSymbolTypeLineEntry:
+ case eSymbolTypeLineHeader:
+ case eSymbolTypeScopeBegin:
+ case eSymbolTypeScopeEnd:
+ case eSymbolTypeAdditional:
+ case eSymbolTypeCompiler:
+ case eSymbolTypeInstrumentation:
+ case eSymbolTypeTrampoline:
+ break;
- if (response.IsUnsupportedResponse())
- {
- // qSymbol is not supported by the current GDB server we are connected to
- m_supports_qSymbol = false;
- return;
- }
- else
- {
- llvm::StringRef response_str(response.GetStringRef());
- if (response_str.startswith("qSymbol:"))
- {
- response.SetFilePos(strlen("qSymbol:"));
- std::string symbol_name;
- if (response.GetHexByteString(symbol_name))
- {
- if (symbol_name.empty())
- return;
-
- addr_t symbol_load_addr = LLDB_INVALID_ADDRESS;
- lldb_private::SymbolContextList sc_list;
- if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list))
- {
- const size_t num_scs = sc_list.GetSize();
- for (size_t sc_idx=0; sc_idx<num_scs && symbol_load_addr == LLDB_INVALID_ADDRESS; ++sc_idx)
- {
- SymbolContext sc;
- if (sc_list.GetContextAtIndex(sc_idx, sc))
- {
- if (sc.symbol)
- {
- switch (sc.symbol->GetType())
- {
- case eSymbolTypeInvalid:
- case eSymbolTypeAbsolute:
- case eSymbolTypeUndefined:
- case eSymbolTypeSourceFile:
- case eSymbolTypeHeaderFile:
- case eSymbolTypeObjectFile:
- case eSymbolTypeCommonBlock:
- case eSymbolTypeBlock:
- case eSymbolTypeLocal:
- case eSymbolTypeParam:
- case eSymbolTypeVariable:
- case eSymbolTypeVariableType:
- case eSymbolTypeLineEntry:
- case eSymbolTypeLineHeader:
- case eSymbolTypeScopeBegin:
- case eSymbolTypeScopeEnd:
- case eSymbolTypeAdditional:
- case eSymbolTypeCompiler:
- case eSymbolTypeInstrumentation:
- case eSymbolTypeTrampoline:
- break;
-
- case eSymbolTypeCode:
- case eSymbolTypeResolver:
- case eSymbolTypeData:
- case eSymbolTypeRuntime:
- case eSymbolTypeException:
- case eSymbolTypeObjCClass:
- case eSymbolTypeObjCMetaClass:
- case eSymbolTypeObjCIVar:
- case eSymbolTypeReExported:
- symbol_load_addr = sc.symbol->GetLoadAddress(&process->GetTarget());
- break;
- }
- }
- }
- }
- }
- // This is the normal path where our symbol lookup was successful and we want
- // to send a packet with the new symbol value and see if another lookup needs to be
- // done.
-
- // Change "packet" to contain the requested symbol value and name
- packet.Clear();
- packet.PutCString("qSymbol:");
- if (symbol_load_addr != LLDB_INVALID_ADDRESS)
- {
- packet.Printf("%" PRIx64, symbol_load_addr);
- symbol_response_provided = true;
- }
- else
- {
- symbol_response_provided = false;
- }
- packet.PutCString(":");
- packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
- continue; // go back to the while loop and send "packet" and wait for another response
- }
+ case eSymbolTypeCode:
+ case eSymbolTypeResolver:
+ case eSymbolTypeData:
+ case eSymbolTypeRuntime:
+ case eSymbolTypeException:
+ case eSymbolTypeObjCClass:
+ case eSymbolTypeObjCMetaClass:
+ case eSymbolTypeObjCIVar:
+ case eSymbolTypeReExported:
+ symbol_load_addr =
+ sc.symbol->GetLoadAddress(&process->GetTarget());
+ break;
+ }
}
+ }
}
- }
- // If we make it here, the symbol request packet response wasn't valid or
- // our symbol lookup failed so we must abort
- return;
+ }
+ // This is the normal path where our symbol lookup was successful
+ // and we want
+ // to send a packet with the new symbol value and see if another
+ // lookup needs to be
+ // done.
+
+ // Change "packet" to contain the requested symbol value and name
+ packet.Clear();
+ packet.PutCString("qSymbol:");
+ if (symbol_load_addr != LLDB_INVALID_ADDRESS) {
+ packet.Printf("%" PRIx64, symbol_load_addr);
+ symbol_response_provided = true;
+ } else {
+ symbol_response_provided = false;
+ }
+ packet.PutCString(":");
+ packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size());
+ continue; // go back to the while loop and send "packet" and wait
+ // for another response
+ }
+ }
+ }
+ }
+ // If we make it here, the symbol request packet response wasn't valid or
+ // our symbol lookup failed so we must abort
+ return;
+
+ } else if (Log *log = ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(
+ GDBR_LOG_PROCESS | GDBR_LOG_PACKETS)) {
+ log->Printf(
+ "GDBRemoteCommunicationClient::%s: Didn't get sequence mutex.",
+ __FUNCTION__);
+ }
+ }
+}
+
+StructuredData::Array *
+GDBRemoteCommunicationClient::GetSupportedStructuredDataPlugins() {
+ if (!m_supported_async_json_packets_is_valid) {
+ // Query the server for the array of supported asynchronous JSON
+ // packets.
+ m_supported_async_json_packets_is_valid = true;
- }
- }
-}
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ // Poll it now.
+ StringExtractorGDBRemote response;
+ const bool send_async = false;
+ if (SendPacketAndWaitForResponse("qStructuredDataPlugins", response,
+ send_async) == PacketResult::Success) {
+ m_supported_async_json_packets_sp =
+ StructuredData::ParseJSON(response.GetStringRef());
+ if (m_supported_async_json_packets_sp &&
+ !m_supported_async_json_packets_sp->GetAsArray()) {
+ // We were returned something other than a JSON array. This
+ // is invalid. Clear it out.
+ if (log)
+ log->Printf("GDBRemoteCommunicationClient::%s(): "
+ "QSupportedAsyncJSONPackets returned invalid "
+ "result: %s",
+ __FUNCTION__, response.GetStringRef().c_str());
+ m_supported_async_json_packets_sp.reset();
+ }
+ } else {
+ if (log)
+ log->Printf("GDBRemoteCommunicationClient::%s(): "
+ "QSupportedAsyncJSONPackets unsupported",
+ __FUNCTION__);
+ }
+
+ if (log && m_supported_async_json_packets_sp) {
+ StreamString stream;
+ m_supported_async_json_packets_sp->Dump(stream);
+ log->Printf("GDBRemoteCommunicationClient::%s(): supported async "
+ "JSON packets: %s",
+ __FUNCTION__, stream.GetData());
+ }
+ }
+
+ return m_supported_async_json_packets_sp
+ ? m_supported_async_json_packets_sp->GetAsArray()
+ : nullptr;
+}
+
+Error GDBRemoteCommunicationClient::ConfigureRemoteStructuredData(
+ const ConstString &type_name, const StructuredData::ObjectSP &config_sp) {
+ Error error;
+
+ if (type_name.GetLength() == 0) {
+ error.SetErrorString("invalid type_name argument");
+ return error;
+ }
+
+ // Build command: Configure{type_name}: serialized config
+ // data.
+ StreamGDBRemote stream;
+ stream.PutCString("QConfigure");
+ stream.PutCString(type_name.AsCString());
+ stream.PutChar(':');
+ if (config_sp) {
+ // Gather the plain-text version of the configuration data.
+ StreamString unescaped_stream;
+ config_sp->Dump(unescaped_stream);
+ unescaped_stream.Flush();
+
+ // Add it to the stream in escaped fashion.
+ stream.PutEscapedBytes(unescaped_stream.GetString().data(),
+ unescaped_stream.GetSize());
+ }
+ stream.Flush();
+
+ // Send the packet.
+ const bool send_async = false;
+ StringExtractorGDBRemote response;
+ auto result =
+ SendPacketAndWaitForResponse(stream.GetString(), response, send_async);
+ if (result == PacketResult::Success) {
+ // We failed if the config result comes back other than OK.
+ if (strcmp(response.GetStringRef().c_str(), "OK") == 0) {
+ // Okay!
+ error.Clear();
+ } else {
+ error.SetErrorStringWithFormat("configuring StructuredData feature "
+ "%s failed with error %s",
+ type_name.AsCString(),
+ response.GetStringRef().c_str());
+ }
+ } else {
+ // Can we get more data here on the failure?
+ error.SetErrorStringWithFormat("configuring StructuredData feature %s "
+ "failed when sending packet: "
+ "PacketResult=%d",
+ type_name.AsCString(), (int)result);
+ }
+ return error;
+}
+
+void GDBRemoteCommunicationClient::OnRunPacketSent(bool first) {
+ GDBRemoteClientBase::OnRunPacketSent(first);
+ m_curr_tid = LLDB_INVALID_THREAD_ID;
+}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 096c4cf..83162a6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -10,8 +10,11 @@
#ifndef liblldb_GDBRemoteCommunicationClient_h_
#define liblldb_GDBRemoteCommunicationClient_h_
+#include "GDBRemoteClientBase.h"
+
// C Includes
// C++ Includes
+#include <chrono>
#include <map>
#include <mutex>
#include <string>
@@ -23,660 +26,563 @@
#include "lldb/Core/StructuredData.h"
#include "lldb/Target/Process.h"
-#include "GDBRemoteCommunication.h"
+#include "llvm/ADT/Optional.h"
namespace lldb_private {
namespace process_gdb_remote {
-class GDBRemoteCommunicationClient : public GDBRemoteCommunication
-{
+class GDBRemoteCommunicationClient : public GDBRemoteClientBase {
public:
- GDBRemoteCommunicationClient();
-
- ~GDBRemoteCommunicationClient() override;
-
- //------------------------------------------------------------------
- // After connecting, send the handshake to the server to make sure
- // we are communicating with it.
- //------------------------------------------------------------------
- bool
- HandshakeWithServer (Error *error_ptr);
-
- PacketResult
- SendPacketAndWaitForResponse (const char *send_payload,
- StringExtractorGDBRemote &response,
- bool send_async);
-
- PacketResult
- SendPacketAndWaitForResponse (const char *send_payload,
- size_t send_length,
- StringExtractorGDBRemote &response,
- bool send_async);
-
- // For packets which specify a range of output to be returned,
- // return all of the output via a series of request packets of the form
- // <prefix>0,<size>
- // <prefix><size>,<size>
- // <prefix><size>*2,<size>
- // <prefix><size>*3,<size>
- // ...
- // until a "$l..." packet is received, indicating the end.
- // (size is in hex; this format is used by a standard gdbserver to
- // return the given portion of the output specified by <prefix>;
- // for example, "qXfer:libraries-svr4:read::fff,1000" means
- // "return a chunk of the xml description file for shared
- // library load addresses, where the chunk starts at offset 0xfff
- // and continues for 0x1000 bytes").
- // Concatenate the resulting server response packets together and
- // return in response_string. If any packet fails, the return value
- // indicates that failure and the returned string value is undefined.
- PacketResult
- SendPacketsAndConcatenateResponses (const char *send_payload_prefix,
- std::string &response_string);
-
- lldb::StateType
- SendContinuePacketAndWaitForResponse (ProcessGDBRemote *process,
- const char *packet_payload,
- size_t packet_length,
- StringExtractorGDBRemote &response);
-
- bool
- SendvContPacket (ProcessGDBRemote *process,
- const char *payload,
- size_t packet_length,
- StringExtractorGDBRemote &response);
-
- bool
- GetThreadSuffixSupported () override;
-
- // This packet is usually sent first and the boolean return value
- // indicates if the packet was send and any response was received
- // even in the response is UNIMPLEMENTED. If the packet failed to
- // get a response, then false is returned. This quickly tells us
- // if we were able to connect and communicate with the remote GDB
- // server
- bool
- QueryNoAckModeSupported ();
-
- void
- GetListThreadsInStopReplySupported ();
-
- bool
- SendAsyncSignal (int signo);
-
- bool
- SendInterrupt (Mutex::Locker &locker,
- uint32_t seconds_to_wait_for_stop,
- bool &timed_out);
-
- lldb::pid_t
- GetCurrentProcessID (bool allow_lazy = true);
-
- bool
- GetLaunchSuccess (std::string &error_str);
-
- bool
- LaunchGDBServer (const char *remote_accept_hostname,
- lldb::pid_t &pid,
- uint16_t &port,
- std::string &socket_name);
-
- size_t
- QueryGDBServer (std::vector<std::pair<uint16_t, std::string>>& connection_urls);
-
- bool
- KillSpawnedProcess (lldb::pid_t pid);
-
- //------------------------------------------------------------------
- /// Sends a GDB remote protocol 'A' packet that delivers program
- /// arguments to the remote server.
- ///
- /// @param[in] argv
- /// A NULL terminated array of const C strings to use as the
- /// arguments.
- ///
- /// @return
- /// Zero if the response was "OK", a positive value if the
- /// the response was "Exx" where xx are two hex digits, or
- /// -1 if the call is unsupported or any other unexpected
- /// response was received.
- //------------------------------------------------------------------
- int
- SendArgumentsPacket (const ProcessLaunchInfo &launch_info);
-
- //------------------------------------------------------------------
- /// Sends a "QEnvironment:NAME=VALUE" packet that will build up the
- /// environment that will get used when launching an application
- /// in conjunction with the 'A' packet. This function can be called
- /// multiple times in a row in order to pass on the desired
- /// environment that the inferior should be launched with.
- ///
- /// @param[in] name_equal_value
- /// A NULL terminated C string that contains a single environment
- /// in the format "NAME=VALUE".
- ///
- /// @return
- /// Zero if the response was "OK", a positive value if the
- /// the response was "Exx" where xx are two hex digits, or
- /// -1 if the call is unsupported or any other unexpected
- /// response was received.
- //------------------------------------------------------------------
- int
- SendEnvironmentPacket (char const *name_equal_value);
-
- int
- SendLaunchArchPacket (const char *arch);
-
- int
- SendLaunchEventDataPacket(const char *data, bool *was_supported = nullptr);
-
- //------------------------------------------------------------------
- /// Sends a "vAttach:PID" where PID is in hex.
- ///
- /// @param[in] pid
- /// A process ID for the remote gdb server to attach to.
- ///
- /// @param[out] response
- /// The response received from the gdb server. If the return
- /// value is zero, \a response will contain a stop reply
- /// packet.
- ///
- /// @return
- /// Zero if the attach was successful, or an error indicating
- /// an error code.
- //------------------------------------------------------------------
- int
- SendAttach (lldb::pid_t pid,
- StringExtractorGDBRemote& response);
-
- //------------------------------------------------------------------
- /// Sends a GDB remote protocol 'I' packet that delivers stdin
- /// data to the remote process.
- ///
- /// @param[in] data
- /// A pointer to stdin data.
- ///
- /// @param[in] data_len
- /// The number of bytes available at \a data.
- ///
- /// @return
- /// Zero if the attach was successful, or an error indicating
- /// an error code.
- //------------------------------------------------------------------
- int
- SendStdinNotification(const char* data, size_t data_len);
-
- //------------------------------------------------------------------
- /// Sets the path to use for stdin/out/err for a process
- /// that will be launched with the 'A' packet.
- ///
- /// @param[in] path
- /// The path to use for stdin/out/err
- ///
- /// @return
- /// Zero if the for success, or an error code for failure.
- //------------------------------------------------------------------
- int
- SetSTDIN(const FileSpec &file_spec);
- int
- SetSTDOUT(const FileSpec &file_spec);
- int
- SetSTDERR(const FileSpec &file_spec);
-
- //------------------------------------------------------------------
- /// Sets the disable ASLR flag to \a enable for a process that will
- /// be launched with the 'A' packet.
- ///
- /// @param[in] enable
- /// A boolean value indicating whether to disable ASLR or not.
- ///
- /// @return
- /// Zero if the for success, or an error code for failure.
- //------------------------------------------------------------------
- int
- SetDisableASLR (bool enable);
-
- //------------------------------------------------------------------
- /// Sets the DetachOnError flag to \a enable for the process controlled by the stub.
- ///
- /// @param[in] enable
- /// A boolean value indicating whether to detach on error or not.
- ///
- /// @return
- /// Zero if the for success, or an error code for failure.
- //------------------------------------------------------------------
- int
- SetDetachOnError (bool enable);
-
- //------------------------------------------------------------------
- /// Sets the working directory to \a path for a process that will
- /// be launched with the 'A' packet for non platform based
- /// connections. If this packet is sent to a GDB server that
- /// implements the platform, it will change the current working
- /// directory for the platform process.
- ///
- /// @param[in] working_dir
- /// The path to a directory to use when launching our process
- ///
- /// @return
- /// Zero if the for success, or an error code for failure.
- //------------------------------------------------------------------
- int
- SetWorkingDir(const FileSpec &working_dir);
-
- //------------------------------------------------------------------
- /// Gets the current working directory of a remote platform GDB
- /// server.
- ///
- /// @param[out] working_dir
- /// The current working directory on the remote platform.
- ///
- /// @return
- /// Boolean for success
- //------------------------------------------------------------------
- bool
- GetWorkingDir(FileSpec &working_dir);
-
- lldb::addr_t
- AllocateMemory (size_t size, uint32_t permissions);
-
- bool
- DeallocateMemory (lldb::addr_t addr);
-
- Error
- Detach (bool keep_stopped);
-
- Error
- GetMemoryRegionInfo (lldb::addr_t addr, MemoryRegionInfo &range_info);
-
- Error
- GetWatchpointSupportInfo (uint32_t &num);
-
- Error
- GetWatchpointSupportInfo (uint32_t &num, bool& after, const ArchSpec &arch);
-
- Error
- GetWatchpointsTriggerAfterInstruction (bool &after, const ArchSpec &arch);
-
- const ArchSpec &
- GetHostArchitecture ();
-
- uint32_t
- GetHostDefaultPacketTimeout();
-
- const ArchSpec &
- GetProcessArchitecture ();
-
- void
- GetRemoteQSupported();
-
- bool
- GetVContSupported (char flavor);
-
- bool
- GetpPacketSupported (lldb::tid_t tid);
-
- bool
- GetxPacketSupported ();
-
- bool
- GetVAttachOrWaitSupported ();
-
- bool
- GetSyncThreadStateSupported();
-
- void
- ResetDiscoverableSettings (bool did_exec);
-
- bool
- GetHostInfo (bool force = false);
-
- bool
- GetDefaultThreadId (lldb::tid_t &tid);
-
- bool
- GetOSVersion (uint32_t &major,
- uint32_t &minor,
- uint32_t &update);
-
- bool
- GetOSBuildString (std::string &s);
-
- bool
- GetOSKernelDescription (std::string &s);
-
- ArchSpec
- GetSystemArchitecture ();
-
- bool
- GetHostname (std::string &s);
-
- lldb::addr_t
- GetShlibInfoAddr();
-
- bool
- GetSupportsThreadSuffix ();
-
- bool
- GetProcessInfo (lldb::pid_t pid, ProcessInstanceInfo &process_info);
-
- uint32_t
- FindProcesses (const ProcessInstanceInfoMatch &process_match_info,
- ProcessInstanceInfoList &process_infos);
-
- bool
- GetUserName (uint32_t uid, std::string &name);
-
- bool
- GetGroupName (uint32_t gid, std::string &name);
-
- bool
- HasFullVContSupport ()
- {
- return GetVContSupported ('A');
- }
+ GDBRemoteCommunicationClient();
+
+ ~GDBRemoteCommunicationClient() override;
+
+ //------------------------------------------------------------------
+ // After connecting, send the handshake to the server to make sure
+ // we are communicating with it.
+ //------------------------------------------------------------------
+ bool HandshakeWithServer(Error *error_ptr);
+
+ // For packets which specify a range of output to be returned,
+ // return all of the output via a series of request packets of the form
+ // <prefix>0,<size>
+ // <prefix><size>,<size>
+ // <prefix><size>*2,<size>
+ // <prefix><size>*3,<size>
+ // ...
+ // until a "$l..." packet is received, indicating the end.
+ // (size is in hex; this format is used by a standard gdbserver to
+ // return the given portion of the output specified by <prefix>;
+ // for example, "qXfer:libraries-svr4:read::fff,1000" means
+ // "return a chunk of the xml description file for shared
+ // library load addresses, where the chunk starts at offset 0xfff
+ // and continues for 0x1000 bytes").
+ // Concatenate the resulting server response packets together and
+ // return in response_string. If any packet fails, the return value
+ // indicates that failure and the returned string value is undefined.
+ PacketResult
+ SendPacketsAndConcatenateResponses(const char *send_payload_prefix,
+ std::string &response_string);
+
+ bool GetThreadSuffixSupported();
+
+ // This packet is usually sent first and the boolean return value
+ // indicates if the packet was send and any response was received
+ // even in the response is UNIMPLEMENTED. If the packet failed to
+ // get a response, then false is returned. This quickly tells us
+ // if we were able to connect and communicate with the remote GDB
+ // server
+ bool QueryNoAckModeSupported();
+
+ void GetListThreadsInStopReplySupported();
+
+ lldb::pid_t GetCurrentProcessID(bool allow_lazy = true);
+
+ bool GetLaunchSuccess(std::string &error_str);
+
+ bool LaunchGDBServer(const char *remote_accept_hostname, lldb::pid_t &pid,
+ uint16_t &port, std::string &socket_name);
+
+ size_t QueryGDBServer(
+ std::vector<std::pair<uint16_t, std::string>> &connection_urls);
+
+ bool KillSpawnedProcess(lldb::pid_t pid);
+
+ //------------------------------------------------------------------
+ /// Sends a GDB remote protocol 'A' packet that delivers program
+ /// arguments to the remote server.
+ ///
+ /// @param[in] argv
+ /// A NULL terminated array of const C strings to use as the
+ /// arguments.
+ ///
+ /// @return
+ /// Zero if the response was "OK", a positive value if the
+ /// the response was "Exx" where xx are two hex digits, or
+ /// -1 if the call is unsupported or any other unexpected
+ /// response was received.
+ //------------------------------------------------------------------
+ int SendArgumentsPacket(const ProcessLaunchInfo &launch_info);
+
+ //------------------------------------------------------------------
+ /// Sends a "QEnvironment:NAME=VALUE" packet that will build up the
+ /// environment that will get used when launching an application
+ /// in conjunction with the 'A' packet. This function can be called
+ /// multiple times in a row in order to pass on the desired
+ /// environment that the inferior should be launched with.
+ ///
+ /// @param[in] name_equal_value
+ /// A NULL terminated C string that contains a single environment
+ /// in the format "NAME=VALUE".
+ ///
+ /// @return
+ /// Zero if the response was "OK", a positive value if the
+ /// the response was "Exx" where xx are two hex digits, or
+ /// -1 if the call is unsupported or any other unexpected
+ /// response was received.
+ //------------------------------------------------------------------
+ int SendEnvironmentPacket(char const *name_equal_value);
+
+ int SendLaunchArchPacket(const char *arch);
+
+ int SendLaunchEventDataPacket(const char *data,
+ bool *was_supported = nullptr);
+
+ //------------------------------------------------------------------
+ /// Sends a "vAttach:PID" where PID is in hex.
+ ///
+ /// @param[in] pid
+ /// A process ID for the remote gdb server to attach to.
+ ///
+ /// @param[out] response
+ /// The response received from the gdb server. If the return
+ /// value is zero, \a response will contain a stop reply
+ /// packet.
+ ///
+ /// @return
+ /// Zero if the attach was successful, or an error indicating
+ /// an error code.
+ //------------------------------------------------------------------
+ int SendAttach(lldb::pid_t pid, StringExtractorGDBRemote &response);
+
+ //------------------------------------------------------------------
+ /// Sends a GDB remote protocol 'I' packet that delivers stdin
+ /// data to the remote process.
+ ///
+ /// @param[in] data
+ /// A pointer to stdin data.
+ ///
+ /// @param[in] data_len
+ /// The number of bytes available at \a data.
+ ///
+ /// @return
+ /// Zero if the attach was successful, or an error indicating
+ /// an error code.
+ //------------------------------------------------------------------
+ int SendStdinNotification(const char *data, size_t data_len);
+
+ //------------------------------------------------------------------
+ /// Sets the path to use for stdin/out/err for a process
+ /// that will be launched with the 'A' packet.
+ ///
+ /// @param[in] path
+ /// The path to use for stdin/out/err
+ ///
+ /// @return
+ /// Zero if the for success, or an error code for failure.
+ //------------------------------------------------------------------
+ int SetSTDIN(const FileSpec &file_spec);
+ int SetSTDOUT(const FileSpec &file_spec);
+ int SetSTDERR(const FileSpec &file_spec);
+
+ //------------------------------------------------------------------
+ /// Sets the disable ASLR flag to \a enable for a process that will
+ /// be launched with the 'A' packet.
+ ///
+ /// @param[in] enable
+ /// A boolean value indicating whether to disable ASLR or not.
+ ///
+ /// @return
+ /// Zero if the for success, or an error code for failure.
+ //------------------------------------------------------------------
+ int SetDisableASLR(bool enable);
+
+ //------------------------------------------------------------------
+ /// Sets the DetachOnError flag to \a enable for the process controlled by the
+ /// stub.
+ ///
+ /// @param[in] enable
+ /// A boolean value indicating whether to detach on error or not.
+ ///
+ /// @return
+ /// Zero if the for success, or an error code for failure.
+ //------------------------------------------------------------------
+ int SetDetachOnError(bool enable);
+
+ //------------------------------------------------------------------
+ /// Sets the working directory to \a path for a process that will
+ /// be launched with the 'A' packet for non platform based
+ /// connections. If this packet is sent to a GDB server that
+ /// implements the platform, it will change the current working
+ /// directory for the platform process.
+ ///
+ /// @param[in] working_dir
+ /// The path to a directory to use when launching our process
+ ///
+ /// @return
+ /// Zero if the for success, or an error code for failure.
+ //------------------------------------------------------------------
+ int SetWorkingDir(const FileSpec &working_dir);
+
+ //------------------------------------------------------------------
+ /// Gets the current working directory of a remote platform GDB
+ /// server.
+ ///
+ /// @param[out] working_dir
+ /// The current working directory on the remote platform.
+ ///
+ /// @return
+ /// Boolean for success
+ //------------------------------------------------------------------
+ bool GetWorkingDir(FileSpec &working_dir);
+
+ lldb::addr_t AllocateMemory(size_t size, uint32_t permissions);
+
+ bool DeallocateMemory(lldb::addr_t addr);
+
+ Error Detach(bool keep_stopped);
+
+ Error GetMemoryRegionInfo(lldb::addr_t addr, MemoryRegionInfo &range_info);
+
+ Error GetWatchpointSupportInfo(uint32_t &num);
+
+ Error GetWatchpointSupportInfo(uint32_t &num, bool &after,
+ const ArchSpec &arch);
+
+ Error GetWatchpointsTriggerAfterInstruction(bool &after,
+ const ArchSpec &arch);
+
+ const ArchSpec &GetHostArchitecture();
+
+ std::chrono::seconds GetHostDefaultPacketTimeout();
+
+ const ArchSpec &GetProcessArchitecture();
+
+ void GetRemoteQSupported();
- bool
- HasAnyVContSupport ()
- {
- return GetVContSupported ('a');
- }
-
- bool
- GetStopReply (StringExtractorGDBRemote &response);
-
- bool
- GetThreadStopInfo (lldb::tid_t tid,
- StringExtractorGDBRemote &response);
-
- bool
- SupportsGDBStoppointPacket (GDBStoppointType type)
- {
- switch (type)
- {
- case eBreakpointSoftware: return m_supports_z0;
- case eBreakpointHardware: return m_supports_z1;
- case eWatchpointWrite: return m_supports_z2;
- case eWatchpointRead: return m_supports_z3;
- case eWatchpointReadWrite: return m_supports_z4;
- default: return false;
- }
- }
+ bool GetVContSupported(char flavor);
- uint8_t
- SendGDBStoppointTypePacket (GDBStoppointType type, // Type of breakpoint or watchpoint
- bool insert, // Insert or remove?
- lldb::addr_t addr, // Address of breakpoint or watchpoint
- uint32_t length); // Byte Size of breakpoint or watchpoint
-
- bool
- SetNonStopMode (const bool enable);
-
- void
- TestPacketSpeed (const uint32_t num_packets, uint32_t max_send, uint32_t max_recv, bool json, Stream &strm);
-
- // This packet is for testing the speed of the interface only. Both
- // the client and server need to support it, but this allows us to
- // measure the packet speed without any other work being done on the
- // other end and avoids any of that work affecting the packet send
- // and response times.
- bool
- SendSpeedTestPacket (uint32_t send_size,
- uint32_t recv_size);
-
- bool
- SetCurrentThread (uint64_t tid);
-
- bool
- SetCurrentThreadForRun (uint64_t tid);
-
- bool
- GetQXferAuxvReadSupported ();
-
- bool
- GetQXferLibrariesReadSupported ();
-
- bool
- GetQXferLibrariesSVR4ReadSupported ();
-
- uint64_t
- GetRemoteMaxPacketSize();
-
- bool
- GetEchoSupported ();
-
- bool
- GetAugmentedLibrariesSVR4ReadSupported ();
-
- bool
- GetQXferFeaturesReadSupported ();
-
- LazyBool
- SupportsAllocDeallocMemory () // const
- {
- // Uncomment this to have lldb pretend the debug server doesn't respond to alloc/dealloc memory packets.
- // m_supports_alloc_dealloc_memory = lldb_private::eLazyBoolNo;
- return m_supports_alloc_dealloc_memory;
- }
+ bool GetpPacketSupported(lldb::tid_t tid);
+
+ bool GetxPacketSupported();
+
+ bool GetVAttachOrWaitSupported();
+
+ bool GetSyncThreadStateSupported();
+
+ void ResetDiscoverableSettings(bool did_exec);
+
+ bool GetHostInfo(bool force = false);
+
+ bool GetDefaultThreadId(lldb::tid_t &tid);
+
+ bool GetOSVersion(uint32_t &major, uint32_t &minor, uint32_t &update);
+
+ bool GetOSBuildString(std::string &s);
+
+ bool GetOSKernelDescription(std::string &s);
+
+ ArchSpec GetSystemArchitecture();
+
+ bool GetHostname(std::string &s);
+
+ lldb::addr_t GetShlibInfoAddr();
+
+ bool GetSupportsThreadSuffix();
+
+ bool GetProcessInfo(lldb::pid_t pid, ProcessInstanceInfo &process_info);
- size_t
- GetCurrentThreadIDs (std::vector<lldb::tid_t> &thread_ids,
- bool &sequence_mutex_unavailable);
-
- bool
- GetInterruptWasSent () const
- {
- return m_interrupt_sent;
+ uint32_t FindProcesses(const ProcessInstanceInfoMatch &process_match_info,
+ ProcessInstanceInfoList &process_infos);
+
+ bool GetUserName(uint32_t uid, std::string &name);
+
+ bool GetGroupName(uint32_t gid, std::string &name);
+
+ bool HasFullVContSupport() { return GetVContSupported('A'); }
+
+ bool HasAnyVContSupport() { return GetVContSupported('a'); }
+
+ bool GetStopReply(StringExtractorGDBRemote &response);
+
+ bool GetThreadStopInfo(lldb::tid_t tid, StringExtractorGDBRemote &response);
+
+ bool SupportsGDBStoppointPacket(GDBStoppointType type) {
+ switch (type) {
+ case eBreakpointSoftware:
+ return m_supports_z0;
+ case eBreakpointHardware:
+ return m_supports_z1;
+ case eWatchpointWrite:
+ return m_supports_z2;
+ case eWatchpointRead:
+ return m_supports_z3;
+ case eWatchpointReadWrite:
+ return m_supports_z4;
+ default:
+ return false;
}
-
- lldb::user_id_t
- OpenFile (const FileSpec& file_spec, uint32_t flags, mode_t mode, Error &error);
-
- bool
- CloseFile (lldb::user_id_t fd, Error &error);
-
- lldb::user_id_t
- GetFileSize (const FileSpec& file_spec);
-
- Error
- GetFilePermissions(const FileSpec &file_spec, uint32_t &file_permissions);
-
- Error
- SetFilePermissions(const FileSpec &file_spec, uint32_t file_permissions);
-
- uint64_t
- ReadFile (lldb::user_id_t fd,
- uint64_t offset,
- void *dst,
- uint64_t dst_len,
- Error &error);
-
- uint64_t
- WriteFile (lldb::user_id_t fd,
- uint64_t offset,
- const void* src,
- uint64_t src_len,
- Error &error);
-
- Error
- CreateSymlink(const FileSpec &src,
- const FileSpec &dst);
-
- Error
- Unlink(const FileSpec &file_spec);
-
- Error
- MakeDirectory(const FileSpec &file_spec, uint32_t mode);
-
- bool
- GetFileExists (const FileSpec& file_spec);
-
- Error
- RunShellCommand(const char *command, // Shouldn't be nullptr
- const FileSpec &working_dir, // Pass empty FileSpec to use the current working directory
- int *status_ptr, // Pass nullptr if you don't want the process exit status
- int *signo_ptr, // Pass nullptr if you don't want the signal that caused the process to exit
- std::string *command_output, // Pass nullptr if you don't want the command output
- uint32_t timeout_sec); // Timeout in seconds to wait for shell program to finish
-
- bool
- CalculateMD5 (const FileSpec& file_spec, uint64_t &high, uint64_t &low);
-
- std::string
- HarmonizeThreadIdsForProfileData (ProcessGDBRemote *process,
- StringExtractorGDBRemote &inputStringExtractor);
-
- bool
- ReadRegister(lldb::tid_t tid,
- uint32_t reg_num, // Must be the eRegisterKindProcessPlugin register number, to be sent to the remote
- StringExtractorGDBRemote &response);
-
- bool
- ReadAllRegisters (lldb::tid_t tid,
- StringExtractorGDBRemote &response);
-
- bool
- SaveRegisterState (lldb::tid_t tid, uint32_t &save_id);
-
- bool
- RestoreRegisterState (lldb::tid_t tid, uint32_t save_id);
-
- const char *
- GetGDBServerProgramName();
-
- uint32_t
- GetGDBServerProgramVersion();
-
- bool
- AvoidGPackets(ProcessGDBRemote *process);
-
- StructuredData::ObjectSP
- GetThreadsInfo();
-
- bool
- GetThreadExtendedInfoSupported();
-
- bool
- GetLoadedDynamicLibrariesInfosSupported();
-
- bool
- GetModuleInfo (const FileSpec& module_file_spec,
- const ArchSpec& arch_spec,
- ModuleSpec &module_spec);
-
- bool
- ReadExtFeature (const lldb_private::ConstString object,
- const lldb_private::ConstString annex,
- std::string & out,
- lldb_private::Error & err);
-
- void
- ServeSymbolLookups(lldb_private::Process *process);
+ }
+
+ uint8_t SendGDBStoppointTypePacket(
+ GDBStoppointType type, // Type of breakpoint or watchpoint
+ bool insert, // Insert or remove?
+ lldb::addr_t addr, // Address of breakpoint or watchpoint
+ uint32_t length); // Byte Size of breakpoint or watchpoint
+
+ bool SetNonStopMode(const bool enable);
+
+ void TestPacketSpeed(const uint32_t num_packets, uint32_t max_send,
+ uint32_t max_recv, uint64_t recv_amount, bool json,
+ Stream &strm);
+
+ // This packet is for testing the speed of the interface only. Both
+ // the client and server need to support it, but this allows us to
+ // measure the packet speed without any other work being done on the
+ // other end and avoids any of that work affecting the packet send
+ // and response times.
+ bool SendSpeedTestPacket(uint32_t send_size, uint32_t recv_size);
+
+ bool SetCurrentThread(uint64_t tid);
+
+ bool SetCurrentThreadForRun(uint64_t tid);
+
+ bool GetQXferAuxvReadSupported();
+
+ bool GetQXferLibrariesReadSupported();
+
+ bool GetQXferLibrariesSVR4ReadSupported();
+
+ uint64_t GetRemoteMaxPacketSize();
+
+ bool GetEchoSupported();
+
+ bool GetAugmentedLibrariesSVR4ReadSupported();
+
+ bool GetQXferFeaturesReadSupported();
+
+ LazyBool SupportsAllocDeallocMemory() // const
+ {
+ // Uncomment this to have lldb pretend the debug server doesn't respond to
+ // alloc/dealloc memory packets.
+ // m_supports_alloc_dealloc_memory = lldb_private::eLazyBoolNo;
+ return m_supports_alloc_dealloc_memory;
+ }
+
+ size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids,
+ bool &sequence_mutex_unavailable);
+
+ lldb::user_id_t OpenFile(const FileSpec &file_spec, uint32_t flags,
+ mode_t mode, Error &error);
+
+ bool CloseFile(lldb::user_id_t fd, Error &error);
+
+ lldb::user_id_t GetFileSize(const FileSpec &file_spec);
+
+ Error GetFilePermissions(const FileSpec &file_spec,
+ uint32_t &file_permissions);
+
+ Error SetFilePermissions(const FileSpec &file_spec,
+ uint32_t file_permissions);
+
+ uint64_t ReadFile(lldb::user_id_t fd, uint64_t offset, void *dst,
+ uint64_t dst_len, Error &error);
+
+ uint64_t WriteFile(lldb::user_id_t fd, uint64_t offset, const void *src,
+ uint64_t src_len, Error &error);
+
+ Error CreateSymlink(const FileSpec &src, const FileSpec &dst);
+
+ Error Unlink(const FileSpec &file_spec);
+
+ Error MakeDirectory(const FileSpec &file_spec, uint32_t mode);
+
+ bool GetFileExists(const FileSpec &file_spec);
+
+ Error RunShellCommand(
+ const char *command, // Shouldn't be nullptr
+ const FileSpec &working_dir, // Pass empty FileSpec to use the current
+ // working directory
+ int *status_ptr, // Pass nullptr if you don't want the process exit status
+ int *signo_ptr, // Pass nullptr if you don't want the signal that caused
+ // the process to exit
+ std::string
+ *command_output, // Pass nullptr if you don't want the command output
+ uint32_t timeout_sec); // Timeout in seconds to wait for shell program to
+ // finish
+
+ bool CalculateMD5(const FileSpec &file_spec, uint64_t &high, uint64_t &low);
+
+ lldb::DataBufferSP ReadRegister(
+ lldb::tid_t tid,
+ uint32_t
+ reg_num); // Must be the eRegisterKindProcessPlugin register number
+
+ lldb::DataBufferSP ReadAllRegisters(lldb::tid_t tid);
+
+ bool
+ WriteRegister(lldb::tid_t tid,
+ uint32_t reg_num, // eRegisterKindProcessPlugin register number
+ llvm::ArrayRef<uint8_t> data);
+
+ bool WriteAllRegisters(lldb::tid_t tid, llvm::ArrayRef<uint8_t> data);
+
+ bool SaveRegisterState(lldb::tid_t tid, uint32_t &save_id);
+
+ bool RestoreRegisterState(lldb::tid_t tid, uint32_t save_id);
+
+ bool SyncThreadState(lldb::tid_t tid);
+
+ const char *GetGDBServerProgramName();
+
+ uint32_t GetGDBServerProgramVersion();
+
+ bool AvoidGPackets(ProcessGDBRemote *process);
+
+ StructuredData::ObjectSP GetThreadsInfo();
+
+ bool GetThreadExtendedInfoSupported();
+
+ bool GetLoadedDynamicLibrariesInfosSupported();
+
+ bool GetSharedCacheInfoSupported();
+
+ bool GetModuleInfo(const FileSpec &module_file_spec,
+ const ArchSpec &arch_spec, ModuleSpec &module_spec);
+
+ llvm::Optional<std::vector<ModuleSpec>>
+ GetModulesInfo(llvm::ArrayRef<FileSpec> module_file_specs,
+ const llvm::Triple &triple);
+
+ bool ReadExtFeature(const lldb_private::ConstString object,
+ const lldb_private::ConstString annex, std::string &out,
+ lldb_private::Error &err);
+
+ void ServeSymbolLookups(lldb_private::Process *process);
+
+ //------------------------------------------------------------------
+ /// Return the feature set supported by the gdb-remote server.
+ ///
+ /// This method returns the remote side's response to the qSupported
+ /// packet. The response is the complete string payload returned
+ /// to the client.
+ ///
+ /// @return
+ /// The string returned by the server to the qSupported query.
+ //------------------------------------------------------------------
+ const std::string &GetServerSupportedFeatures() const {
+ return m_qSupported_response;
+ }
+
+ //------------------------------------------------------------------
+ /// Return the array of async JSON packet types supported by the remote.
+ ///
+ /// This method returns the remote side's array of supported JSON
+ /// packet types as a list of type names. Each of the results are
+ /// expected to have an Enable{type_name} command to enable and configure
+ /// the related feature. Each type_name for an enabled feature will
+ /// possibly send async-style packets that contain a payload of a
+ /// binhex-encoded JSON dictionary. The dictionary will have a
+ /// string field named 'type', that contains the type_name of the
+ /// supported packet type.
+ ///
+ /// There is a Plugin category called structured-data plugins.
+ /// A plugin indicates whether it knows how to handle a type_name.
+ /// If so, it can be used to process the async JSON packet.
+ ///
+ /// @return
+ /// The string returned by the server to the qSupported query.
+ //------------------------------------------------------------------
+ lldb_private::StructuredData::Array *GetSupportedStructuredDataPlugins();
+
+ //------------------------------------------------------------------
+ /// Configure a StructuredData feature on the remote end.
+ ///
+ /// @see \b Process::ConfigureStructuredData(...) for details.
+ //------------------------------------------------------------------
+ Error
+ ConfigureRemoteStructuredData(const ConstString &type_name,
+ const StructuredData::ObjectSP &config_sp);
protected:
- LazyBool m_supports_not_sending_acks;
- LazyBool m_supports_thread_suffix;
- LazyBool m_supports_threads_in_stop_reply;
- LazyBool m_supports_vCont_all;
- LazyBool m_supports_vCont_any;
- LazyBool m_supports_vCont_c;
- LazyBool m_supports_vCont_C;
- LazyBool m_supports_vCont_s;
- LazyBool m_supports_vCont_S;
- LazyBool m_qHostInfo_is_valid;
- LazyBool m_curr_pid_is_valid;
- LazyBool m_qProcessInfo_is_valid;
- LazyBool m_qGDBServerVersion_is_valid;
- LazyBool m_supports_alloc_dealloc_memory;
- LazyBool m_supports_memory_region_info;
- LazyBool m_supports_watchpoint_support_info;
- LazyBool m_supports_detach_stay_stopped;
- LazyBool m_watchpoints_trigger_after_instruction;
- LazyBool m_attach_or_wait_reply;
- LazyBool m_prepare_for_reg_writing_reply;
- LazyBool m_supports_p;
- LazyBool m_supports_x;
- LazyBool m_avoid_g_packets;
- LazyBool m_supports_QSaveRegisterState;
- LazyBool m_supports_qXfer_auxv_read;
- LazyBool m_supports_qXfer_libraries_read;
- LazyBool m_supports_qXfer_libraries_svr4_read;
- LazyBool m_supports_qXfer_features_read;
- LazyBool m_supports_augmented_libraries_svr4_read;
- LazyBool m_supports_jThreadExtendedInfo;
- LazyBool m_supports_jLoadedDynamicLibrariesInfos;
-
- bool
- m_supports_qProcessInfoPID:1,
- m_supports_qfProcessInfo:1,
- m_supports_qUserName:1,
- m_supports_qGroupName:1,
- m_supports_qThreadStopInfo:1,
- m_supports_z0:1,
- m_supports_z1:1,
- m_supports_z2:1,
- m_supports_z3:1,
- m_supports_z4:1,
- m_supports_QEnvironment:1,
- m_supports_QEnvironmentHexEncoded:1,
- m_supports_qSymbol:1,
- m_qSymbol_requests_done:1,
- m_supports_qModuleInfo:1,
- m_supports_jThreadsInfo:1;
-
- lldb::pid_t m_curr_pid;
- lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations
- lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for continue, step, etc
-
- uint32_t m_num_supported_hardware_watchpoints;
-
- // If we need to send a packet while the target is running, the m_async_XXX
- // member variables take care of making this happen.
- std::recursive_mutex m_async_mutex;
- Predicate<bool> m_async_packet_predicate;
- std::string m_async_packet;
- PacketResult m_async_result;
- StringExtractorGDBRemote m_async_response;
- int m_async_signal; // We were asked to deliver a signal to the inferior process.
- bool m_interrupt_sent;
- std::string m_partial_profile_data;
- std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map;
-
- ArchSpec m_host_arch;
- ArchSpec m_process_arch;
- uint32_t m_os_version_major;
- uint32_t m_os_version_minor;
- uint32_t m_os_version_update;
- std::string m_os_build;
- std::string m_os_kernel;
- std::string m_hostname;
- std::string m_gdb_server_name; // from reply to qGDBServerVersion, empty if qGDBServerVersion is not supported
- uint32_t m_gdb_server_version; // from reply to qGDBServerVersion, zero if qGDBServerVersion is not supported
- uint32_t m_default_packet_timeout;
- uint64_t m_max_packet_size; // as returned by qSupported
-
- PacketResult
- SendPacketAndWaitForResponseNoLock (const char *payload,
- size_t payload_length,
- StringExtractorGDBRemote &response);
-
- bool
- GetCurrentProcessInfo (bool allow_lazy_pid = true);
-
- bool
- GetGDBServerVersion();
-
- // Given the list of compression types that the remote debug stub can support,
- // possibly enable compression if we find an encoding we can handle.
- void
- MaybeEnableCompression (std::vector<std::string> supported_compressions);
-
- bool
- DecodeProcessInfoResponse (StringExtractorGDBRemote &response,
- ProcessInstanceInfo &process_info);
+ LazyBool m_supports_not_sending_acks;
+ LazyBool m_supports_thread_suffix;
+ LazyBool m_supports_threads_in_stop_reply;
+ LazyBool m_supports_vCont_all;
+ LazyBool m_supports_vCont_any;
+ LazyBool m_supports_vCont_c;
+ LazyBool m_supports_vCont_C;
+ LazyBool m_supports_vCont_s;
+ LazyBool m_supports_vCont_S;
+ LazyBool m_qHostInfo_is_valid;
+ LazyBool m_curr_pid_is_valid;
+ LazyBool m_qProcessInfo_is_valid;
+ LazyBool m_qGDBServerVersion_is_valid;
+ LazyBool m_supports_alloc_dealloc_memory;
+ LazyBool m_supports_memory_region_info;
+ LazyBool m_supports_watchpoint_support_info;
+ LazyBool m_supports_detach_stay_stopped;
+ LazyBool m_watchpoints_trigger_after_instruction;
+ LazyBool m_attach_or_wait_reply;
+ LazyBool m_prepare_for_reg_writing_reply;
+ LazyBool m_supports_p;
+ LazyBool m_supports_x;
+ LazyBool m_avoid_g_packets;
+ LazyBool m_supports_QSaveRegisterState;
+ LazyBool m_supports_qXfer_auxv_read;
+ LazyBool m_supports_qXfer_libraries_read;
+ LazyBool m_supports_qXfer_libraries_svr4_read;
+ LazyBool m_supports_qXfer_features_read;
+ LazyBool m_supports_augmented_libraries_svr4_read;
+ LazyBool m_supports_jThreadExtendedInfo;
+ LazyBool m_supports_jLoadedDynamicLibrariesInfos;
+ LazyBool m_supports_jGetSharedCacheInfo;
+
+ bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1,
+ m_supports_qUserName : 1, m_supports_qGroupName : 1,
+ m_supports_qThreadStopInfo : 1, m_supports_z0 : 1, m_supports_z1 : 1,
+ m_supports_z2 : 1, m_supports_z3 : 1, m_supports_z4 : 1,
+ m_supports_QEnvironment : 1, m_supports_QEnvironmentHexEncoded : 1,
+ m_supports_qSymbol : 1, m_qSymbol_requests_done : 1,
+ m_supports_qModuleInfo : 1, m_supports_jThreadsInfo : 1,
+ m_supports_jModulesInfo : 1;
+
+ lldb::pid_t m_curr_pid;
+ lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all
+ // other operations
+ lldb::tid_t m_curr_tid_run; // Current gdb remote protocol thread index for
+ // continue, step, etc
+
+ uint32_t m_num_supported_hardware_watchpoints;
+
+ ArchSpec m_host_arch;
+ ArchSpec m_process_arch;
+ uint32_t m_os_version_major;
+ uint32_t m_os_version_minor;
+ uint32_t m_os_version_update;
+ std::string m_os_build;
+ std::string m_os_kernel;
+ std::string m_hostname;
+ std::string m_gdb_server_name; // from reply to qGDBServerVersion, empty if
+ // qGDBServerVersion is not supported
+ uint32_t m_gdb_server_version; // from reply to qGDBServerVersion, zero if
+ // qGDBServerVersion is not supported
+ std::chrono::seconds m_default_packet_timeout;
+ uint64_t m_max_packet_size; // as returned by qSupported
+ std::string m_qSupported_response; // the complete response to qSupported
+
+ bool m_supported_async_json_packets_is_valid;
+ lldb_private::StructuredData::ObjectSP m_supported_async_json_packets_sp;
+
+ bool GetCurrentProcessInfo(bool allow_lazy_pid = true);
+
+ bool GetGDBServerVersion();
+
+ // Given the list of compression types that the remote debug stub can support,
+ // possibly enable compression if we find an encoding we can handle.
+ void MaybeEnableCompression(std::vector<std::string> supported_compressions);
+
+ bool DecodeProcessInfoResponse(StringExtractorGDBRemote &response,
+ ProcessInstanceInfo &process_info);
+
+ void OnRunPacketSent(bool first) override;
+
+ PacketResult SendThreadSpecificPacketAndWaitForResponse(
+ lldb::tid_t tid, StreamString &&payload,
+ StringExtractorGDBRemote &response, bool send_async);
private:
- DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationClient);
+ DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient);
};
} // namespace process_gdb_remote
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
index 4ee66b8..934824e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp
@@ -25,114 +25,96 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
-GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(const char *comm_name,
- const char *listener_name) :
- GDBRemoteCommunication (comm_name, listener_name),
- m_exit_now (false)
-{
-}
+GDBRemoteCommunicationServer::GDBRemoteCommunicationServer(
+ const char *comm_name, const char *listener_name)
+ : GDBRemoteCommunication(comm_name, listener_name), m_exit_now(false) {}
-GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer()
-{
-}
+GDBRemoteCommunicationServer::~GDBRemoteCommunicationServer() {}
void GDBRemoteCommunicationServer::RegisterPacketHandler(
- StringExtractorGDBRemote::ServerPacketType packet_type,
- PacketHandler handler)
-{
- m_packet_handlers[packet_type] = std::move(handler);
+ StringExtractorGDBRemote::ServerPacketType packet_type,
+ PacketHandler handler) {
+ m_packet_handlers[packet_type] = std::move(handler);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServer::GetPacketAndSendResponse (uint32_t timeout_usec,
- Error &error,
- bool &interrupt,
- bool &quit)
-{
- StringExtractorGDBRemote packet;
-
- PacketResult packet_result = WaitForPacketWithTimeoutMicroSecondsNoLock (packet, timeout_usec, false);
- if (packet_result == PacketResult::Success)
- {
- const StringExtractorGDBRemote::ServerPacketType packet_type = packet.GetServerPacketType ();
- switch (packet_type)
- {
- case StringExtractorGDBRemote::eServerPacketType_nack:
- case StringExtractorGDBRemote::eServerPacketType_ack:
- break;
-
- case StringExtractorGDBRemote::eServerPacketType_invalid:
- error.SetErrorString("invalid packet");
- quit = true;
- break;
-
- case StringExtractorGDBRemote::eServerPacketType_unimplemented:
- packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str());
- break;
-
- default:
- auto handler_it = m_packet_handlers.find(packet_type);
- if (handler_it == m_packet_handlers.end())
- packet_result = SendUnimplementedResponse (packet.GetStringRef().c_str());
- else
- packet_result = handler_it->second (packet, error, interrupt, quit);
- break;
- }
+GDBRemoteCommunicationServer::GetPacketAndSendResponse(
+ Timeout<std::micro> timeout, Error &error, bool &interrupt, bool &quit) {
+ StringExtractorGDBRemote packet;
+
+ PacketResult packet_result = WaitForPacketNoLock(packet, timeout, false);
+ if (packet_result == PacketResult::Success) {
+ const StringExtractorGDBRemote::ServerPacketType packet_type =
+ packet.GetServerPacketType();
+ switch (packet_type) {
+ case StringExtractorGDBRemote::eServerPacketType_nack:
+ case StringExtractorGDBRemote::eServerPacketType_ack:
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_invalid:
+ error.SetErrorString("invalid packet");
+ quit = true;
+ break;
+
+ case StringExtractorGDBRemote::eServerPacketType_unimplemented:
+ packet_result = SendUnimplementedResponse(packet.GetStringRef().c_str());
+ break;
+
+ default:
+ auto handler_it = m_packet_handlers.find(packet_type);
+ if (handler_it == m_packet_handlers.end())
+ packet_result =
+ SendUnimplementedResponse(packet.GetStringRef().c_str());
+ else
+ packet_result = handler_it->second(packet, error, interrupt, quit);
+ break;
}
- else
- {
- if (!IsConnected())
- {
- error.SetErrorString("lost connection");
- quit = true;
- }
- else
- {
- error.SetErrorString("timeout");
- }
+ } else {
+ if (!IsConnected()) {
+ error.SetErrorString("lost connection");
+ quit = true;
+ } else {
+ error.SetErrorString("timeout");
}
+ }
- // Check if anything occurred that would force us to want to exit.
- if (m_exit_now)
- quit = true;
+ // Check if anything occurred that would force us to want to exit.
+ if (m_exit_now)
+ quit = true;
- return packet_result;
+ return packet_result;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *)
-{
- // TODO: Log the packet we aren't handling...
- return SendPacketNoLock ("", 0);
+GDBRemoteCommunicationServer::SendUnimplementedResponse(const char *) {
+ // TODO: Log the packet we aren't handling...
+ return SendPacketNoLock("");
}
-
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err)
-{
- char packet[16];
- int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err);
- assert (packet_len < (int)sizeof(packet));
- return SendPacketNoLock (packet, packet_len);
+GDBRemoteCommunicationServer::SendErrorResponse(uint8_t err) {
+ char packet[16];
+ int packet_len = ::snprintf(packet, sizeof(packet), "E%2.2x", err);
+ assert(packet_len < (int)sizeof(packet));
+ return SendPacketNoLock(llvm::StringRef(packet, packet_len));
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServer::SendIllFormedResponse (const StringExtractorGDBRemote &failed_packet, const char *message)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)", __FUNCTION__, failed_packet.GetStringRef ().c_str (), message ? message : "");
- return SendErrorResponse (0x03);
+GDBRemoteCommunicationServer::SendIllFormedResponse(
+ const StringExtractorGDBRemote &failed_packet, const char *message) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServer::%s: ILLFORMED: '%s' (%s)",
+ __FUNCTION__, failed_packet.GetStringRef().c_str(),
+ message ? message : "");
+ return SendErrorResponse(0x03);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServer::SendOKResponse ()
-{
- return SendPacketNoLock ("OK", 2);
+GDBRemoteCommunicationServer::SendOKResponse() {
+ return SendPacketNoLock("OK");
}
-bool
-GDBRemoteCommunicationServer::HandshakeWithClient()
-{
- return GetAck() == PacketResult::Success;
+bool GDBRemoteCommunicationServer::HandshakeWithClient() {
+ return GetAck() == PacketResult::Success;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
index 1d512bf..0c583e6 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h
@@ -17,8 +17,8 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private-forward.h"
#include "GDBRemoteCommunication.h"
+#include "lldb/lldb-private-forward.h"
class StringExtractorGDBRemote;
@@ -27,52 +27,47 @@ namespace process_gdb_remote {
class ProcessGDBRemote;
-class GDBRemoteCommunicationServer : public GDBRemoteCommunication
-{
+class GDBRemoteCommunicationServer : public GDBRemoteCommunication {
public:
- using PortMap = std::map<uint16_t, lldb::pid_t>;
- using PacketHandler = std::function<PacketResult(StringExtractorGDBRemote &packet,
- Error &error,
- bool &interrupt,
- bool &quit)>;
+ using PortMap = std::map<uint16_t, lldb::pid_t>;
+ using PacketHandler =
+ std::function<PacketResult(StringExtractorGDBRemote &packet, Error &error,
+ bool &interrupt, bool &quit)>;
- GDBRemoteCommunicationServer(const char *comm_name,
- const char *listener_name);
+ GDBRemoteCommunicationServer(const char *comm_name,
+ const char *listener_name);
- ~GDBRemoteCommunicationServer() override;
+ ~GDBRemoteCommunicationServer() override;
- void RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type,
- PacketHandler handler);
+ void
+ RegisterPacketHandler(StringExtractorGDBRemote::ServerPacketType packet_type,
+ PacketHandler handler);
- PacketResult
- GetPacketAndSendResponse (uint32_t timeout_usec,
- Error &error,
- bool &interrupt,
- bool &quit);
+ PacketResult GetPacketAndSendResponse(Timeout<std::micro> timeout,
+ Error &error, bool &interrupt,
+ bool &quit);
- // After connecting, do a little handshake with the client to make sure
- // we are at least communicating
- bool
- HandshakeWithClient ();
+ // After connecting, do a little handshake with the client to make sure
+ // we are at least communicating
+ bool HandshakeWithClient();
protected:
- std::map<StringExtractorGDBRemote::ServerPacketType, PacketHandler> m_packet_handlers;
- bool m_exit_now; // use in asynchronous handling to indicate process should exit.
+ std::map<StringExtractorGDBRemote::ServerPacketType, PacketHandler>
+ m_packet_handlers;
+ bool m_exit_now; // use in asynchronous handling to indicate process should
+ // exit.
- PacketResult
- SendUnimplementedResponse (const char *packet);
+ PacketResult SendUnimplementedResponse(const char *packet);
- PacketResult
- SendErrorResponse (uint8_t error);
+ PacketResult SendErrorResponse(uint8_t error);
- PacketResult
- SendIllFormedResponse (const StringExtractorGDBRemote &packet, const char *error_message);
+ PacketResult SendIllFormedResponse(const StringExtractorGDBRemote &packet,
+ const char *error_message);
- PacketResult
- SendOKResponse ();
+ PacketResult SendOKResponse();
private:
- DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServer);
+ DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServer);
};
} // namespace process_gdb_remote
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
index 26a2e69..e4e6810 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp
@@ -12,12 +12,16 @@
#include <errno.h>
// C Includes
+
+#ifdef __APPLE__
+#include <TargetConditionals.h>
+#endif
+
// C++ Includes
-#include <cstring>
#include <chrono>
+#include <cstring>
// Other libraries and framework includes
-#include "llvm/ADT/Triple.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/StreamGDBRemote.h"
@@ -34,6 +38,8 @@
#include "lldb/Target/FileAction.h"
#include "lldb/Target/Platform.h"
#include "lldb/Target/Process.h"
+#include "lldb/Utility/JSON.h"
+#include "llvm/ADT/Triple.h"
// Project includes
#include "ProcessGDBRemoteLog.h"
@@ -43,1214 +49,1252 @@
#include "lldb/Host/android/HostInfoAndroid.h"
#endif
+#include "llvm/ADT/StringSwitch.h"
+
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
#ifdef __ANDROID__
- const static uint32_t g_default_packet_timeout_sec = 20; // seconds
+const static uint32_t g_default_packet_timeout_sec = 20; // seconds
#else
- const static uint32_t g_default_packet_timeout_sec = 0; // not specified
+const static uint32_t g_default_packet_timeout_sec = 0; // not specified
#endif
//----------------------------------------------------------------------
// GDBRemoteCommunicationServerCommon constructor
//----------------------------------------------------------------------
-GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name) :
- GDBRemoteCommunicationServer (comm_name, listener_name),
- m_process_launch_info (),
- m_process_launch_error (),
- m_proc_infos (),
- m_proc_infos_index (0),
- m_thread_suffix_supported (false),
- m_list_threads_in_stop_reply (false)
-{
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A,
- &GDBRemoteCommunicationServerCommon::Handle_A);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QEnvironment,
- &GDBRemoteCommunicationServerCommon::Handle_QEnvironment);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QEnvironmentHexEncoded,
- &GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qfProcessInfo,
- &GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGroupName,
- &GDBRemoteCommunicationServerCommon::Handle_qGroupName);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qHostInfo,
- &GDBRemoteCommunicationServerCommon::Handle_qHostInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QLaunchArch,
- &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess,
- &GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply,
- &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qEcho,
- &GDBRemoteCommunicationServerCommon::Handle_qEcho);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qModuleInfo,
- &GDBRemoteCommunicationServerCommon::Handle_qModuleInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod,
- &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir,
- &GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_shell,
- &GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID,
- &GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError,
- &GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetSTDERR,
- &GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetSTDIN,
- &GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT,
- &GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qSpeedTest,
- &GDBRemoteCommunicationServerCommon::Handle_qSpeedTest);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qsProcessInfo,
- &GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode,
- &GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qSupported,
- &GDBRemoteCommunicationServerCommon::Handle_qSupported);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported,
- &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qUserName,
- &GDBRemoteCommunicationServerCommon::Handle_qUserName);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_close,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_Close);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_exists,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_Exists);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_md5,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_MD5);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_mode,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_Mode);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_open,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_Open);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_pread,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_pRead);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_pwrite,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_size,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_Size);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_stat,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_Stat);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_symlink,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_symlink);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vFile_unlink,
- &GDBRemoteCommunicationServerCommon::Handle_vFile_unlink);
+GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon(
+ const char *comm_name, const char *listener_name)
+ : GDBRemoteCommunicationServer(comm_name, listener_name),
+ m_process_launch_info(), m_process_launch_error(), m_proc_infos(),
+ m_proc_infos_index(0), m_thread_suffix_supported(false),
+ m_list_threads_in_stop_reply(false) {
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_A,
+ &GDBRemoteCommunicationServerCommon::Handle_A);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QEnvironment,
+ &GDBRemoteCommunicationServerCommon::Handle_QEnvironment);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QEnvironmentHexEncoded,
+ &GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qfProcessInfo,
+ &GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qGroupName,
+ &GDBRemoteCommunicationServerCommon::Handle_qGroupName);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qHostInfo,
+ &GDBRemoteCommunicationServerCommon::Handle_qHostInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QLaunchArch,
+ &GDBRemoteCommunicationServerCommon::Handle_QLaunchArch);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qLaunchSuccess,
+ &GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QListThreadsInStopReply,
+ &GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qEcho,
+ &GDBRemoteCommunicationServerCommon::Handle_qEcho);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qModuleInfo,
+ &GDBRemoteCommunicationServerCommon::Handle_qModuleInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jModulesInfo,
+ &GDBRemoteCommunicationServerCommon::Handle_jModulesInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod,
+ &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir,
+ &GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qPlatform_shell,
+ &GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID,
+ &GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QSetDetachOnError,
+ &GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QSetSTDERR,
+ &GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QSetSTDIN,
+ &GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QSetSTDOUT,
+ &GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qSpeedTest,
+ &GDBRemoteCommunicationServerCommon::Handle_qSpeedTest);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qsProcessInfo,
+ &GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode,
+ &GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qSupported,
+ &GDBRemoteCommunicationServerCommon::Handle_qSupported);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QThreadSuffixSupported,
+ &GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qUserName,
+ &GDBRemoteCommunicationServerCommon::Handle_qUserName);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_close,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_Close);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_exists,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_Exists);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_md5,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_MD5);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_mode,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_Mode);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_open,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_Open);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_pread,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_pRead);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_pwrite,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_size,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_Size);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_stat,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_Stat);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_symlink,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_symlink);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vFile_unlink,
+ &GDBRemoteCommunicationServerCommon::Handle_vFile_unlink);
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon()
-{
-}
+GDBRemoteCommunicationServerCommon::~GDBRemoteCommunicationServerCommon() {}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qHostInfo (StringExtractorGDBRemote &packet)
-{
- StreamString response;
+GDBRemoteCommunicationServerCommon::Handle_qHostInfo(
+ StringExtractorGDBRemote &packet) {
+ StreamString response;
- // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
+ // $cputype:16777223;cpusubtype:3;ostype:Darwin;vendor:apple;endian:little;ptrsize:8;#00
- ArchSpec host_arch(HostInfo::GetArchitecture());
- const llvm::Triple &host_triple = host_arch.GetTriple();
- response.PutCString("triple:");
- response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
- response.Printf (";ptrsize:%u;",host_arch.GetAddressByteSize());
-
- const char* distribution_id = host_arch.GetDistributionId ().AsCString ();
- if (distribution_id)
- {
- response.PutCString("distribution_id:");
- response.PutCStringAsRawHex8(distribution_id);
- response.PutCString(";");
- }
+ ArchSpec host_arch(HostInfo::GetArchitecture());
+ const llvm::Triple &host_triple = host_arch.GetTriple();
+ response.PutCString("triple:");
+ response.PutCStringAsRawHex8(host_triple.getTriple().c_str());
+ response.Printf(";ptrsize:%u;", host_arch.GetAddressByteSize());
+
+ const char *distribution_id = host_arch.GetDistributionId().AsCString();
+ if (distribution_id) {
+ response.PutCString("distribution_id:");
+ response.PutCStringAsRawHex8(distribution_id);
+ response.PutCString(";");
+ }
- // Only send out MachO info when lldb-platform/llgs is running on a MachO host.
#if defined(__APPLE__)
- uint32_t cpu = host_arch.GetMachOCPUType();
- uint32_t sub = host_arch.GetMachOCPUSubType();
- if (cpu != LLDB_INVALID_CPUTYPE)
- response.Printf ("cputype:%u;", cpu);
- if (sub != LLDB_INVALID_CPUTYPE)
- response.Printf ("cpusubtype:%u;", sub);
-
- if (cpu == ArchSpec::kCore_arm_any)
- response.Printf("watchpoint_exceptions_received:before;"); // On armv7 we use "synchronous" watchpoints which means the exception is delivered before the instruction executes.
- else
- response.Printf("watchpoint_exceptions_received:after;");
+ // For parity with debugserver, we'll include the vendor key.
+ response.PutCString("vendor:apple;");
+
+ // Send out MachO info.
+ uint32_t cpu = host_arch.GetMachOCPUType();
+ uint32_t sub = host_arch.GetMachOCPUSubType();
+ if (cpu != LLDB_INVALID_CPUTYPE)
+ response.Printf("cputype:%u;", cpu);
+ if (sub != LLDB_INVALID_CPUTYPE)
+ response.Printf("cpusubtype:%u;", sub);
+
+ if (cpu == ArchSpec::kCore_arm_any) {
+// Indicate the OS type.
+#if defined(TARGET_OS_TV) && TARGET_OS_TV == 1
+ response.PutCString("ostype:tvos;");
+#elif defined(TARGET_OS_WATCH) && TARGET_OS_WATCH == 1
+ response.PutCString("ostype:watchos;");
#else
- if (host_arch.GetMachine() == llvm::Triple::aarch64 ||
- host_arch.GetMachine() == llvm::Triple::aarch64_be ||
- host_arch.GetMachine() == llvm::Triple::arm ||
- host_arch.GetMachine() == llvm::Triple::armeb ||
- host_arch.GetMachine() == llvm::Triple::mips64 ||
- host_arch.GetMachine() == llvm::Triple::mips64el ||
- host_arch.GetMachine() == llvm::Triple::mips ||
- host_arch.GetMachine() == llvm::Triple::mipsel)
- response.Printf("watchpoint_exceptions_received:before;");
- else
- response.Printf("watchpoint_exceptions_received:after;");
+ response.PutCString("ostype:ios;");
#endif
- switch (endian::InlHostByteOrder())
- {
- case eByteOrderBig: response.PutCString ("endian:big;"); break;
- case eByteOrderLittle: response.PutCString ("endian:little;"); break;
- case eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
- default: response.PutCString ("endian:unknown;"); break;
- }
+ // On arm, we use "synchronous" watchpoints which means the exception is
+ // delivered before the instruction executes.
+ response.PutCString("watchpoint_exceptions_received:before;");
+ } else {
+ response.PutCString("ostype:macosx;");
+ response.Printf("watchpoint_exceptions_received:after;");
+ }
- uint32_t major = UINT32_MAX;
- uint32_t minor = UINT32_MAX;
- uint32_t update = UINT32_MAX;
- if (HostInfo::GetOSVersion(major, minor, update))
- {
- if (major != UINT32_MAX)
- {
- response.Printf("os_version:%u", major);
- if (minor != UINT32_MAX)
- {
- response.Printf(".%u", minor);
- if (update != UINT32_MAX)
- response.Printf(".%u", update);
- }
- response.PutChar(';');
- }
- }
+#else
+ if (host_arch.GetMachine() == llvm::Triple::aarch64 ||
+ host_arch.GetMachine() == llvm::Triple::aarch64_be ||
+ host_arch.GetMachine() == llvm::Triple::arm ||
+ host_arch.GetMachine() == llvm::Triple::armeb ||
+ host_arch.GetMachine() == llvm::Triple::mips64 ||
+ host_arch.GetMachine() == llvm::Triple::mips64el ||
+ host_arch.GetMachine() == llvm::Triple::mips ||
+ host_arch.GetMachine() == llvm::Triple::mipsel)
+ response.Printf("watchpoint_exceptions_received:before;");
+ else
+ response.Printf("watchpoint_exceptions_received:after;");
+#endif
- std::string s;
- if (HostInfo::GetOSBuildString(s))
- {
- response.PutCString ("os_build:");
- response.PutCStringAsRawHex8(s.c_str());
- response.PutChar(';');
- }
- if (HostInfo::GetOSKernelDescription(s))
- {
- response.PutCString ("os_kernel:");
- response.PutCStringAsRawHex8(s.c_str());
- response.PutChar(';');
+ switch (endian::InlHostByteOrder()) {
+ case eByteOrderBig:
+ response.PutCString("endian:big;");
+ break;
+ case eByteOrderLittle:
+ response.PutCString("endian:little;");
+ break;
+ case eByteOrderPDP:
+ response.PutCString("endian:pdp;");
+ break;
+ default:
+ response.PutCString("endian:unknown;");
+ break;
+ }
+
+ uint32_t major = UINT32_MAX;
+ uint32_t minor = UINT32_MAX;
+ uint32_t update = UINT32_MAX;
+ if (HostInfo::GetOSVersion(major, minor, update)) {
+ if (major != UINT32_MAX) {
+ response.Printf("os_version:%u", major);
+ if (minor != UINT32_MAX) {
+ response.Printf(".%u", minor);
+ if (update != UINT32_MAX)
+ response.Printf(".%u", update);
+ }
+ response.PutChar(';');
}
+ }
+
+ std::string s;
+ if (HostInfo::GetOSBuildString(s)) {
+ response.PutCString("os_build:");
+ response.PutCStringAsRawHex8(s.c_str());
+ response.PutChar(';');
+ }
+ if (HostInfo::GetOSKernelDescription(s)) {
+ response.PutCString("os_kernel:");
+ response.PutCStringAsRawHex8(s.c_str());
+ response.PutChar(';');
+ }
#if defined(__APPLE__)
#if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
- // For iOS devices, we are connected through a USB Mux so we never pretend
- // to actually have a hostname as far as the remote lldb that is connecting
- // to this lldb-platform is concerned
- response.PutCString ("hostname:");
- response.PutCStringAsRawHex8("127.0.0.1");
+ // For iOS devices, we are connected through a USB Mux so we never pretend
+ // to actually have a hostname as far as the remote lldb that is connecting
+ // to this lldb-platform is concerned
+ response.PutCString("hostname:");
+ response.PutCStringAsRawHex8("127.0.0.1");
+ response.PutChar(';');
+#else // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+ if (HostInfo::GetHostname(s)) {
+ response.PutCString("hostname:");
+ response.PutCStringAsRawHex8(s.c_str());
response.PutChar(';');
-#else // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
- if (HostInfo::GetHostname(s))
- {
- response.PutCString ("hostname:");
- response.PutCStringAsRawHex8(s.c_str());
- response.PutChar(';');
- }
-#endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
+ }
+#endif // #if defined(__arm__) || defined(__arm64__) || defined(__aarch64__)
-#else // #if defined(__APPLE__)
- if (HostInfo::GetHostname(s))
- {
- response.PutCString ("hostname:");
- response.PutCStringAsRawHex8(s.c_str());
- response.PutChar(';');
- }
-#endif // #if defined(__APPLE__)
+#else // #if defined(__APPLE__)
+ if (HostInfo::GetHostname(s)) {
+ response.PutCString("hostname:");
+ response.PutCStringAsRawHex8(s.c_str());
+ response.PutChar(';');
+ }
+#endif // #if defined(__APPLE__)
- if (g_default_packet_timeout_sec > 0)
- response.Printf ("default_packet_timeout:%u;", g_default_packet_timeout_sec);
+ if (g_default_packet_timeout_sec > 0)
+ response.Printf("default_packet_timeout:%u;", g_default_packet_timeout_sec);
- return SendPacketNoLock (response.GetData(), response.GetSize());
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet)
-{
- // Packet format: "qProcessInfoPID:%i" where %i is the pid
- packet.SetFilePos (::strlen ("qProcessInfoPID:"));
- lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID);
- if (pid != LLDB_INVALID_PROCESS_ID)
- {
- ProcessInstanceInfo proc_info;
- if (Host::GetProcessInfo (pid, proc_info))
- {
- StreamString response;
- CreateProcessInfoResponse (proc_info, response);
- return SendPacketNoLock (response.GetData(), response.GetSize());
- }
+GDBRemoteCommunicationServerCommon::Handle_qProcessInfoPID(
+ StringExtractorGDBRemote &packet) {
+ // Packet format: "qProcessInfoPID:%i" where %i is the pid
+ packet.SetFilePos(::strlen("qProcessInfoPID:"));
+ lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID);
+ if (pid != LLDB_INVALID_PROCESS_ID) {
+ ProcessInstanceInfo proc_info;
+ if (Host::GetProcessInfo(pid, proc_info)) {
+ StreamString response;
+ CreateProcessInfoResponse(proc_info, response);
+ return SendPacketNoLock(response.GetString());
}
- return SendErrorResponse (1);
+ }
+ return SendErrorResponse(1);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo (StringExtractorGDBRemote &packet)
-{
- m_proc_infos_index = 0;
- m_proc_infos.Clear();
-
- ProcessInstanceInfoMatch match_info;
- packet.SetFilePos(::strlen ("qfProcessInfo"));
- if (packet.GetChar() == ':')
- {
-
- std::string key;
- std::string value;
- while (packet.GetNameColonValue(key, value))
- {
- bool success = true;
- if (key.compare("name") == 0)
- {
- StringExtractor extractor;
- extractor.GetStringRef().swap(value);
- extractor.GetHexByteString (value);
- match_info.GetProcessInfo().GetExecutableFile().SetFile(value.c_str(), false);
- }
- else if (key.compare("name_match") == 0)
- {
- if (value.compare("equals") == 0)
- {
- match_info.SetNameMatchType (eNameMatchEquals);
- }
- else if (value.compare("starts_with") == 0)
- {
- match_info.SetNameMatchType (eNameMatchStartsWith);
- }
- else if (value.compare("ends_with") == 0)
- {
- match_info.SetNameMatchType (eNameMatchEndsWith);
- }
- else if (value.compare("contains") == 0)
- {
- match_info.SetNameMatchType (eNameMatchContains);
- }
- else if (value.compare("regex") == 0)
- {
- match_info.SetNameMatchType (eNameMatchRegularExpression);
- }
- else
- {
- success = false;
- }
- }
- else if (key.compare("pid") == 0)
- {
- match_info.GetProcessInfo().SetProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
- }
- else if (key.compare("parent_pid") == 0)
- {
- match_info.GetProcessInfo().SetParentProcessID (StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success));
- }
- else if (key.compare("uid") == 0)
- {
- match_info.GetProcessInfo().SetUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
- }
- else if (key.compare("gid") == 0)
- {
- match_info.GetProcessInfo().SetGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
- }
- else if (key.compare("euid") == 0)
- {
- match_info.GetProcessInfo().SetEffectiveUserID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
- }
- else if (key.compare("egid") == 0)
- {
- match_info.GetProcessInfo().SetEffectiveGroupID (StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0, &success));
- }
- else if (key.compare("all_users") == 0)
- {
- match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success));
- }
- else if (key.compare("triple") == 0)
- {
- match_info.GetProcessInfo().GetArchitecture().SetTriple (value.c_str(), NULL);
- }
- else
- {
- success = false;
- }
-
- if (!success)
- return SendErrorResponse (2);
- }
- }
-
- if (Host::FindProcesses (match_info, m_proc_infos))
- {
- // We found something, return the first item by calling the get
- // subsequent process info packet handler...
- return Handle_qsProcessInfo (packet);
+GDBRemoteCommunicationServerCommon::Handle_qfProcessInfo(
+ StringExtractorGDBRemote &packet) {
+ m_proc_infos_index = 0;
+ m_proc_infos.Clear();
+
+ ProcessInstanceInfoMatch match_info;
+ packet.SetFilePos(::strlen("qfProcessInfo"));
+ if (packet.GetChar() == ':') {
+ llvm::StringRef key;
+ llvm::StringRef value;
+ while (packet.GetNameColonValue(key, value)) {
+ bool success = true;
+ if (key.equals("name")) {
+ StringExtractor extractor(value);
+ std::string file;
+ extractor.GetHexByteString(file);
+ match_info.GetProcessInfo().GetExecutableFile().SetFile(file, false);
+ } else if (key.equals("name_match")) {
+ NameMatchType name_match =
+ llvm::StringSwitch<NameMatchType>(value)
+ .Case("equals", eNameMatchEquals)
+ .Case("starts_with", eNameMatchStartsWith)
+ .Case("ends_with", eNameMatchEndsWith)
+ .Case("contains", eNameMatchContains)
+ .Case("regex", eNameMatchRegularExpression)
+ .Default(eNameMatchIgnore);
+ match_info.SetNameMatchType(name_match);
+ if (name_match == eNameMatchIgnore)
+ return SendErrorResponse(2);
+ } else if (key.equals("pid")) {
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ if (value.getAsInteger(0, pid))
+ return SendErrorResponse(2);
+ match_info.GetProcessInfo().SetProcessID(pid);
+ } else if (key.equals("parent_pid")) {
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+ if (value.getAsInteger(0, pid))
+ return SendErrorResponse(2);
+ match_info.GetProcessInfo().SetParentProcessID(pid);
+ } else if (key.equals("uid")) {
+ uint32_t uid = UINT32_MAX;
+ if (value.getAsInteger(0, uid))
+ return SendErrorResponse(2);
+ match_info.GetProcessInfo().SetUserID(uid);
+ } else if (key.equals("gid")) {
+ uint32_t gid = UINT32_MAX;
+ if (value.getAsInteger(0, gid))
+ return SendErrorResponse(2);
+ match_info.GetProcessInfo().SetGroupID(gid);
+ } else if (key.equals("euid")) {
+ uint32_t uid = UINT32_MAX;
+ if (value.getAsInteger(0, uid))
+ return SendErrorResponse(2);
+ match_info.GetProcessInfo().SetEffectiveUserID(uid);
+ } else if (key.equals("egid")) {
+ uint32_t gid = UINT32_MAX;
+ if (value.getAsInteger(0, gid))
+ return SendErrorResponse(2);
+ match_info.GetProcessInfo().SetEffectiveGroupID(gid);
+ } else if (key.equals("all_users")) {
+ match_info.SetMatchAllUsers(
+ Args::StringToBoolean(value, false, &success));
+ } else if (key.equals("triple")) {
+ match_info.GetProcessInfo().GetArchitecture().SetTriple(
+ value.str().c_str(), NULL);
+ } else {
+ success = false;
+ }
+
+ if (!success)
+ return SendErrorResponse(2);
}
- return SendErrorResponse (3);
+ }
+
+ if (Host::FindProcesses(match_info, m_proc_infos)) {
+ // We found something, return the first item by calling the get
+ // subsequent process info packet handler...
+ return Handle_qsProcessInfo(packet);
+ }
+ return SendErrorResponse(3);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo (StringExtractorGDBRemote &packet)
-{
- if (m_proc_infos_index < m_proc_infos.GetSize())
- {
- StreamString response;
- CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
- ++m_proc_infos_index;
- return SendPacketNoLock (response.GetData(), response.GetSize());
- }
- return SendErrorResponse (4);
+GDBRemoteCommunicationServerCommon::Handle_qsProcessInfo(
+ StringExtractorGDBRemote &packet) {
+ if (m_proc_infos_index < m_proc_infos.GetSize()) {
+ StreamString response;
+ CreateProcessInfoResponse(
+ m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response);
+ ++m_proc_infos_index;
+ return SendPacketNoLock(response.GetString());
+ }
+ return SendErrorResponse(4);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qUserName (StringExtractorGDBRemote &packet)
-{
+GDBRemoteCommunicationServerCommon::Handle_qUserName(
+ StringExtractorGDBRemote &packet) {
#if !defined(LLDB_DISABLE_POSIX)
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__);
-
- // Packet format: "qUserName:%i" where %i is the uid
- packet.SetFilePos(::strlen ("qUserName:"));
- uint32_t uid = packet.GetU32 (UINT32_MAX);
- if (uid != UINT32_MAX)
- {
- std::string name;
- if (HostInfo::LookupUserName(uid, name))
- {
- StreamString response;
- response.PutCStringAsRawHex8 (name.c_str());
- return SendPacketNoLock (response.GetData(), response.GetSize());
- }
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerCommon::%s begin", __FUNCTION__);
+
+ // Packet format: "qUserName:%i" where %i is the uid
+ packet.SetFilePos(::strlen("qUserName:"));
+ uint32_t uid = packet.GetU32(UINT32_MAX);
+ if (uid != UINT32_MAX) {
+ std::string name;
+ if (HostInfo::LookupUserName(uid, name)) {
+ StreamString response;
+ response.PutCStringAsRawHex8(name.c_str());
+ return SendPacketNoLock(response.GetString());
}
- if (log)
- log->Printf("GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__);
+ }
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerCommon::%s end", __FUNCTION__);
#endif
- return SendErrorResponse (5);
-
+ return SendErrorResponse(5);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qGroupName (StringExtractorGDBRemote &packet)
-{
+GDBRemoteCommunicationServerCommon::Handle_qGroupName(
+ StringExtractorGDBRemote &packet) {
#if !defined(LLDB_DISABLE_POSIX)
- // Packet format: "qGroupName:%i" where %i is the gid
- packet.SetFilePos(::strlen ("qGroupName:"));
- uint32_t gid = packet.GetU32 (UINT32_MAX);
- if (gid != UINT32_MAX)
- {
- std::string name;
- if (HostInfo::LookupGroupName(gid, name))
- {
- StreamString response;
- response.PutCStringAsRawHex8 (name.c_str());
- return SendPacketNoLock (response.GetData(), response.GetSize());
- }
+ // Packet format: "qGroupName:%i" where %i is the gid
+ packet.SetFilePos(::strlen("qGroupName:"));
+ uint32_t gid = packet.GetU32(UINT32_MAX);
+ if (gid != UINT32_MAX) {
+ std::string name;
+ if (HostInfo::LookupGroupName(gid, name)) {
+ StreamString response;
+ response.PutCStringAsRawHex8(name.c_str());
+ return SendPacketNoLock(response.GetString());
}
+ }
#endif
- return SendErrorResponse (6);
+ return SendErrorResponse(6);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qSpeedTest (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("qSpeedTest:"));
-
- std::string key;
- std::string value;
- bool success = packet.GetNameColonValue(key, value);
- if (success && key.compare("response_size") == 0)
- {
- uint32_t response_size = StringConvert::ToUInt32(value.c_str(), 0, 0, &success);
- if (success)
- {
- if (response_size == 0)
- return SendOKResponse();
- StreamString response;
- uint32_t bytes_left = response_size;
- response.PutCString("data:");
- while (bytes_left > 0)
- {
- if (bytes_left >= 26)
- {
- response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- bytes_left -= 26;
- }
- else
- {
- response.Printf ("%*.*s;", bytes_left, bytes_left, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- bytes_left = 0;
- }
- }
- return SendPacketNoLock (response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerCommon::Handle_qSpeedTest(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("qSpeedTest:"));
+
+ llvm::StringRef key;
+ llvm::StringRef value;
+ bool success = packet.GetNameColonValue(key, value);
+ if (success && key.equals("response_size")) {
+ uint32_t response_size = 0;
+ if (!value.getAsInteger(0, response_size)) {
+ if (response_size == 0)
+ return SendOKResponse();
+ StreamString response;
+ uint32_t bytes_left = response_size;
+ response.PutCString("data:");
+ while (bytes_left > 0) {
+ if (bytes_left >= 26) {
+ response.PutCString("ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ bytes_left -= 26;
+ } else {
+ response.Printf("%*.*s;", bytes_left, bytes_left,
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ bytes_left = 0;
}
+ }
+ return SendPacketNoLock(response.GetString());
}
- return SendErrorResponse (7);
+ }
+ return SendErrorResponse(7);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_Open (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("vFile:open:"));
- std::string path;
- packet.GetHexByteStringTerminatedBy(path,',');
- if (!path.empty())
- {
- if (packet.GetChar() == ',')
- {
- uint32_t flags = File::ConvertOpenOptionsForPOSIXOpen(
- packet.GetHexMaxU32(false, 0));
- if (packet.GetChar() == ',')
- {
- mode_t mode = packet.GetHexMaxU32(false, 0600);
- Error error;
- const FileSpec path_spec{path, true};
- int fd = ::open(path_spec.GetCString(), flags, mode);
- const int save_errno = fd == -1 ? errno : 0;
- StreamString response;
- response.PutChar('F');
- response.Printf("%i", fd);
- if (save_errno)
- response.Printf(",%i", save_errno);
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
- }
+GDBRemoteCommunicationServerCommon::Handle_vFile_Open(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("vFile:open:"));
+ std::string path;
+ packet.GetHexByteStringTerminatedBy(path, ',');
+ if (!path.empty()) {
+ if (packet.GetChar() == ',') {
+ uint32_t flags =
+ File::ConvertOpenOptionsForPOSIXOpen(packet.GetHexMaxU32(false, 0));
+ if (packet.GetChar() == ',') {
+ mode_t mode = packet.GetHexMaxU32(false, 0600);
+ Error error;
+ const FileSpec path_spec{path, true};
+ int fd = ::open(path_spec.GetCString(), flags, mode);
+ const int save_errno = fd == -1 ? errno : 0;
+ StreamString response;
+ response.PutChar('F');
+ response.Printf("%i", fd);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ return SendPacketNoLock(response.GetString());
+ }
}
- return SendErrorResponse(18);
+ }
+ return SendErrorResponse(18);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_Close (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("vFile:close:"));
- int fd = packet.GetS32(-1);
- Error error;
- int err = -1;
- int save_errno = 0;
- if (fd >= 0)
- {
- err = close(fd);
- save_errno = err == -1 ? errno : 0;
- }
- else
- {
- save_errno = EINVAL;
- }
- StreamString response;
- response.PutChar('F');
- response.Printf("%i", err);
- if (save_errno)
- response.Printf(",%i", save_errno);
- return SendPacketNoLock(response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerCommon::Handle_vFile_Close(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("vFile:close:"));
+ int fd = packet.GetS32(-1);
+ Error error;
+ int err = -1;
+ int save_errno = 0;
+ if (fd >= 0) {
+ err = close(fd);
+ save_errno = err == -1 ? errno : 0;
+ } else {
+ save_errno = EINVAL;
+ }
+ StreamString response;
+ response.PutChar('F');
+ response.Printf("%i", err);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_pRead (StringExtractorGDBRemote &packet)
-{
+GDBRemoteCommunicationServerCommon::Handle_vFile_pRead(
+ StringExtractorGDBRemote &packet) {
#ifdef _WIN32
- // Not implemented on Windows
- return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_vFile_pRead() unimplemented");
+ // Not implemented on Windows
+ return SendUnimplementedResponse(
+ "GDBRemoteCommunicationServerCommon::Handle_vFile_pRead() unimplemented");
#else
- StreamGDBRemote response;
- packet.SetFilePos(::strlen("vFile:pread:"));
- int fd = packet.GetS32(-1);
- if (packet.GetChar() == ',')
- {
- uint64_t count = packet.GetU64(UINT64_MAX);
- if (packet.GetChar() == ',')
- {
- uint64_t offset = packet.GetU64(UINT32_MAX);
- if (count == UINT64_MAX)
- {
- response.Printf("F-1:%i", EINVAL);
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
-
- std::string buffer(count, 0);
- const ssize_t bytes_read = ::pread (fd, &buffer[0], buffer.size(), offset);
- const int save_errno = bytes_read == -1 ? errno : 0;
- response.PutChar('F');
- response.Printf("%zi", bytes_read);
- if (save_errno)
- response.Printf(",%i", save_errno);
- else
- {
- response.PutChar(';');
- response.PutEscapedBytes(&buffer[0], bytes_read);
- }
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
+ StreamGDBRemote response;
+ packet.SetFilePos(::strlen("vFile:pread:"));
+ int fd = packet.GetS32(-1);
+ if (packet.GetChar() == ',') {
+ uint64_t count = packet.GetU64(UINT64_MAX);
+ if (packet.GetChar() == ',') {
+ uint64_t offset = packet.GetU64(UINT32_MAX);
+ if (count == UINT64_MAX) {
+ response.Printf("F-1:%i", EINVAL);
+ return SendPacketNoLock(response.GetString());
+ }
+
+ std::string buffer(count, 0);
+ const ssize_t bytes_read = ::pread(fd, &buffer[0], buffer.size(), offset);
+ const int save_errno = bytes_read == -1 ? errno : 0;
+ response.PutChar('F');
+ response.Printf("%zi", bytes_read);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ else {
+ response.PutChar(';');
+ response.PutEscapedBytes(&buffer[0], bytes_read);
+ }
+ return SendPacketNoLock(response.GetString());
}
- return SendErrorResponse(21);
+ }
+ return SendErrorResponse(21);
#endif
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite (StringExtractorGDBRemote &packet)
-{
+GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite(
+ StringExtractorGDBRemote &packet) {
#ifdef _WIN32
- return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_vFile_pWrite() unimplemented");
+ return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_"
+ "vFile_pWrite() unimplemented");
#else
- packet.SetFilePos(::strlen("vFile:pwrite:"));
-
- StreamGDBRemote response;
- response.PutChar('F');
-
- int fd = packet.GetU32(UINT32_MAX);
- if (packet.GetChar() == ',')
- {
- off_t offset = packet.GetU64(UINT32_MAX);
- if (packet.GetChar() == ',')
- {
- std::string buffer;
- if (packet.GetEscapedBinaryData(buffer))
- {
- const ssize_t bytes_written = ::pwrite (fd, buffer.data(), buffer.size(), offset);
- const int save_errno = bytes_written == -1 ? errno : 0;
- response.Printf("%zi", bytes_written);
- if (save_errno)
- response.Printf(",%i", save_errno);
- }
- else
- {
- response.Printf ("-1,%i", EINVAL);
- }
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
+ packet.SetFilePos(::strlen("vFile:pwrite:"));
+
+ StreamGDBRemote response;
+ response.PutChar('F');
+
+ int fd = packet.GetU32(UINT32_MAX);
+ if (packet.GetChar() == ',') {
+ off_t offset = packet.GetU64(UINT32_MAX);
+ if (packet.GetChar() == ',') {
+ std::string buffer;
+ if (packet.GetEscapedBinaryData(buffer)) {
+ const ssize_t bytes_written =
+ ::pwrite(fd, buffer.data(), buffer.size(), offset);
+ const int save_errno = bytes_written == -1 ? errno : 0;
+ response.Printf("%zi", bytes_written);
+ if (save_errno)
+ response.Printf(",%i", save_errno);
+ } else {
+ response.Printf("-1,%i", EINVAL);
+ }
+ return SendPacketNoLock(response.GetString());
}
- return SendErrorResponse(27);
+ }
+ return SendErrorResponse(27);
#endif
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_Size (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("vFile:size:"));
- std::string path;
- packet.GetHexByteString(path);
- if (!path.empty())
- {
- lldb::user_id_t retcode = FileSystem::GetFileSize(FileSpec(path.c_str(), false));
- StreamString response;
- response.PutChar('F');
- response.PutHex64(retcode);
- if (retcode == UINT64_MAX)
- {
- response.PutChar(',');
- response.PutHex64(retcode); // TODO: replace with Host::GetSyswideErrorCode()
- }
- return SendPacketNoLock(response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerCommon::Handle_vFile_Size(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("vFile:size:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (!path.empty()) {
+ lldb::user_id_t retcode = FileSystem::GetFileSize(FileSpec(path, false));
+ StreamString response;
+ response.PutChar('F');
+ response.PutHex64(retcode);
+ if (retcode == UINT64_MAX) {
+ response.PutChar(',');
+ response.PutHex64(
+ retcode); // TODO: replace with Host::GetSyswideErrorCode()
}
- return SendErrorResponse(22);
+ return SendPacketNoLock(response.GetString());
+ }
+ return SendErrorResponse(22);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_Mode (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("vFile:mode:"));
- std::string path;
- packet.GetHexByteString(path);
- if (!path.empty())
- {
- Error error;
- const uint32_t mode = File::GetPermissions(FileSpec{path, true}, error);
- StreamString response;
- response.Printf("F%u", mode);
- if (mode == 0 || error.Fail())
- response.Printf(",%i", (int)error.GetError());
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
- return SendErrorResponse(23);
+GDBRemoteCommunicationServerCommon::Handle_vFile_Mode(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("vFile:mode:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (!path.empty()) {
+ Error error;
+ const uint32_t mode = File::GetPermissions(FileSpec{path, true}, error);
+ StreamString response;
+ response.Printf("F%u", mode);
+ if (mode == 0 || error.Fail())
+ response.Printf(",%i", (int)error.GetError());
+ return SendPacketNoLock(response.GetString());
+ }
+ return SendErrorResponse(23);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_Exists (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("vFile:exists:"));
- std::string path;
- packet.GetHexByteString(path);
- if (!path.empty())
- {
- bool retcode = FileSystem::GetFileExists(FileSpec(path.c_str(), false));
- StreamString response;
- response.PutChar('F');
- response.PutChar(',');
- if (retcode)
- response.PutChar('1');
- else
- response.PutChar('0');
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
- return SendErrorResponse(24);
+GDBRemoteCommunicationServerCommon::Handle_vFile_Exists(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("vFile:exists:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (!path.empty()) {
+ bool retcode = FileSystem::GetFileExists(FileSpec(path, false));
+ StreamString response;
+ response.PutChar('F');
+ response.PutChar(',');
+ if (retcode)
+ response.PutChar('1');
+ else
+ response.PutChar('0');
+ return SendPacketNoLock(response.GetString());
+ }
+ return SendErrorResponse(24);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_symlink (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("vFile:symlink:"));
- std::string dst, src;
- packet.GetHexByteStringTerminatedBy(dst, ',');
- packet.GetChar(); // Skip ',' char
- packet.GetHexByteString(src);
- Error error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false});
- StreamString response;
- response.Printf("F%u,%u", error.GetError(), error.GetError());
- return SendPacketNoLock(response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerCommon::Handle_vFile_symlink(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("vFile:symlink:"));
+ std::string dst, src;
+ packet.GetHexByteStringTerminatedBy(dst, ',');
+ packet.GetChar(); // Skip ',' char
+ packet.GetHexByteString(src);
+ Error error = FileSystem::Symlink(FileSpec{src, true}, FileSpec{dst, false});
+ StreamString response;
+ response.Printf("F%u,%u", error.GetError(), error.GetError());
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_unlink (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("vFile:unlink:"));
- std::string path;
- packet.GetHexByteString(path);
- Error error = FileSystem::Unlink(FileSpec{path, true});
- StreamString response;
- response.Printf("F%u,%u", error.GetError(), error.GetError());
- return SendPacketNoLock(response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerCommon::Handle_vFile_unlink(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("vFile:unlink:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ Error error = FileSystem::Unlink(FileSpec{path, true});
+ StreamString response;
+ response.Printf("F%u,%u", error.GetError(), error.GetError());
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("qPlatform_shell:"));
- std::string path;
- std::string working_dir;
- packet.GetHexByteStringTerminatedBy(path,',');
- if (!path.empty())
- {
- if (packet.GetChar() == ',')
- {
- // FIXME: add timeout to qPlatform_shell packet
- // uint32_t timeout = packet.GetHexMaxU32(false, 32);
- uint32_t timeout = 10;
- if (packet.GetChar() == ',')
- packet.GetHexByteString(working_dir);
- int status, signo;
- std::string output;
- Error err = Host::RunShellCommand(path.c_str(),
- FileSpec{working_dir, true},
- &status, &signo, &output, timeout);
- StreamGDBRemote response;
- if (err.Fail())
- {
- response.PutCString("F,");
- response.PutHex32(UINT32_MAX);
- }
- else
- {
- response.PutCString("F,");
- response.PutHex32(status);
- response.PutChar(',');
- response.PutHex32(signo);
- response.PutChar(',');
- response.PutEscapedBytes(output.c_str(), output.size());
- }
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
+GDBRemoteCommunicationServerCommon::Handle_qPlatform_shell(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("qPlatform_shell:"));
+ std::string path;
+ std::string working_dir;
+ packet.GetHexByteStringTerminatedBy(path, ',');
+ if (!path.empty()) {
+ if (packet.GetChar() == ',') {
+ // FIXME: add timeout to qPlatform_shell packet
+ // uint32_t timeout = packet.GetHexMaxU32(false, 32);
+ uint32_t timeout = 10;
+ if (packet.GetChar() == ',')
+ packet.GetHexByteString(working_dir);
+ int status, signo;
+ std::string output;
+ Error err =
+ Host::RunShellCommand(path.c_str(), FileSpec{working_dir, true},
+ &status, &signo, &output, timeout);
+ StreamGDBRemote response;
+ if (err.Fail()) {
+ response.PutCString("F,");
+ response.PutHex32(UINT32_MAX);
+ } else {
+ response.PutCString("F,");
+ response.PutHex32(status);
+ response.PutChar(',');
+ response.PutHex32(signo);
+ response.PutChar(',');
+ response.PutEscapedBytes(output.c_str(), output.size());
+ }
+ return SendPacketNoLock(response.GetString());
}
- return SendErrorResponse(24);
+ }
+ return SendErrorResponse(24);
}
-
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_Stat (StringExtractorGDBRemote &packet)
-{
- return SendUnimplementedResponse("GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented");
+GDBRemoteCommunicationServerCommon::Handle_vFile_Stat(
+ StringExtractorGDBRemote &packet) {
+ return SendUnimplementedResponse(
+ "GDBRemoteCommunicationServerCommon::Handle_vFile_Stat() unimplemented");
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_vFile_MD5 (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("vFile:MD5:"));
- std::string path;
- packet.GetHexByteString(path);
- if (!path.empty())
- {
- uint64_t a,b;
- StreamGDBRemote response;
- if (!FileSystem::CalculateMD5(FileSpec(path.c_str(), false), a, b))
- {
- response.PutCString("F,");
- response.PutCString("x");
- }
- else
- {
- response.PutCString("F,");
- response.PutHex64(a);
- response.PutHex64(b);
- }
- return SendPacketNoLock(response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerCommon::Handle_vFile_MD5(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("vFile:MD5:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ if (!path.empty()) {
+ uint64_t a, b;
+ StreamGDBRemote response;
+ if (!FileSystem::CalculateMD5(FileSpec(path, false), a, b)) {
+ response.PutCString("F,");
+ response.PutCString("x");
+ } else {
+ response.PutCString("F,");
+ response.PutHex64(a);
+ response.PutHex64(b);
}
- return SendErrorResponse(25);
+ return SendPacketNoLock(response.GetString());
+ }
+ return SendErrorResponse(25);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("qPlatform_mkdir:"));
- mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
- if (packet.GetChar() == ',')
- {
- std::string path;
- packet.GetHexByteString(path);
- Error error = FileSystem::MakeDirectory(FileSpec{path, false}, mode);
-
- StreamGDBRemote response;
- response.Printf("F%u", error.GetError());
-
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
- return SendErrorResponse(20);
+GDBRemoteCommunicationServerCommon::Handle_qPlatform_mkdir(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("qPlatform_mkdir:"));
+ mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
+ if (packet.GetChar() == ',') {
+ std::string path;
+ packet.GetHexByteString(path);
+ Error error = FileSystem::MakeDirectory(FileSpec{path, false}, mode);
+
+ StreamGDBRemote response;
+ response.Printf("F%u", error.GetError());
+
+ return SendPacketNoLock(response.GetString());
+ }
+ return SendErrorResponse(20);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("qPlatform_chmod:"));
+GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("qPlatform_chmod:"));
- mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
- if (packet.GetChar() == ',')
- {
- std::string path;
- packet.GetHexByteString(path);
- Error error = FileSystem::SetFilePermissions(FileSpec{path, true}, mode);
+ mode_t mode = packet.GetHexMaxU32(false, UINT32_MAX);
+ if (packet.GetChar() == ',') {
+ std::string path;
+ packet.GetHexByteString(path);
+ Error error = FileSystem::SetFilePermissions(FileSpec{path, true}, mode);
- StreamGDBRemote response;
- response.Printf("F%u", error.GetError());
+ StreamGDBRemote response;
+ response.Printf("F%u", error.GetError());
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
- return SendErrorResponse(19);
+ return SendPacketNoLock(response.GetString());
+ }
+ return SendErrorResponse(19);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qSupported (StringExtractorGDBRemote &packet)
-{
- StreamGDBRemote response;
-
- // Features common to lldb-platform and llgs.
- uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet size--debugger can always use less
- response.Printf ("PacketSize=%x", max_packet_size);
-
- response.PutCString (";QStartNoAckMode+");
- response.PutCString (";QThreadSuffixSupported+");
- response.PutCString (";QListThreadsInStopReply+");
- response.PutCString (";qEcho+");
+GDBRemoteCommunicationServerCommon::Handle_qSupported(
+ StringExtractorGDBRemote &packet) {
+ StreamGDBRemote response;
+
+ // Features common to lldb-platform and llgs.
+ uint32_t max_packet_size = 128 * 1024; // 128KBytes is a reasonable max packet
+ // size--debugger can always use less
+ response.Printf("PacketSize=%x", max_packet_size);
+
+ response.PutCString(";QStartNoAckMode+");
+ response.PutCString(";QThreadSuffixSupported+");
+ response.PutCString(";QListThreadsInStopReply+");
+ response.PutCString(";qEcho+");
#if defined(__linux__)
- response.PutCString (";qXfer:auxv:read+");
+ response.PutCString(";qXfer:auxv:read+");
#endif
- return SendPacketNoLock(response.GetData(), response.GetSize());
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet)
-{
- m_thread_suffix_supported = true;
- return SendOKResponse();
+GDBRemoteCommunicationServerCommon::Handle_QThreadSuffixSupported(
+ StringExtractorGDBRemote &packet) {
+ m_thread_suffix_supported = true;
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet)
-{
- m_list_threads_in_stop_reply = true;
- return SendOKResponse();
+GDBRemoteCommunicationServerCommon::Handle_QListThreadsInStopReply(
+ StringExtractorGDBRemote &packet) {
+ m_list_threads_in_stop_reply = true;
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("QSetDetachOnError:"));
- if (packet.GetU32(0))
- m_process_launch_info.GetFlags().Set (eLaunchFlagDetachOnError);
- else
- m_process_launch_info.GetFlags().Clear (eLaunchFlagDetachOnError);
- return SendOKResponse ();
+GDBRemoteCommunicationServerCommon::Handle_QSetDetachOnError(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("QSetDetachOnError:"));
+ if (packet.GetU32(0))
+ m_process_launch_info.GetFlags().Set(eLaunchFlagDetachOnError);
+ else
+ m_process_launch_info.GetFlags().Clear(eLaunchFlagDetachOnError);
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet)
-{
- // Send response first before changing m_send_acks to we ack this packet
- PacketResult packet_result = SendOKResponse ();
- m_send_acks = false;
- return packet_result;
+GDBRemoteCommunicationServerCommon::Handle_QStartNoAckMode(
+ StringExtractorGDBRemote &packet) {
+ // Send response first before changing m_send_acks to we ack this packet
+ PacketResult packet_result = SendOKResponse();
+ m_send_acks = false;
+ return packet_result;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("QSetSTDIN:"));
- FileAction file_action;
- std::string path;
- packet.GetHexByteString(path);
- const bool read = false;
- const bool write = true;
- if (file_action.Open(STDIN_FILENO, FileSpec{path, false}, read, write))
- {
- m_process_launch_info.AppendFileAction(file_action);
- return SendOKResponse ();
- }
- return SendErrorResponse (15);
+GDBRemoteCommunicationServerCommon::Handle_QSetSTDIN(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("QSetSTDIN:"));
+ FileAction file_action;
+ std::string path;
+ packet.GetHexByteString(path);
+ const bool read = true;
+ const bool write = false;
+ if (file_action.Open(STDIN_FILENO, FileSpec{path, false}, read, write)) {
+ m_process_launch_info.AppendFileAction(file_action);
+ return SendOKResponse();
+ }
+ return SendErrorResponse(15);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("QSetSTDOUT:"));
- FileAction file_action;
- std::string path;
- packet.GetHexByteString(path);
- const bool read = true;
- const bool write = false;
- if (file_action.Open(STDOUT_FILENO, FileSpec{path, false}, read, write))
- {
- m_process_launch_info.AppendFileAction(file_action);
- return SendOKResponse ();
- }
- return SendErrorResponse (16);
+GDBRemoteCommunicationServerCommon::Handle_QSetSTDOUT(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("QSetSTDOUT:"));
+ FileAction file_action;
+ std::string path;
+ packet.GetHexByteString(path);
+ const bool read = false;
+ const bool write = true;
+ if (file_action.Open(STDOUT_FILENO, FileSpec{path, false}, read, write)) {
+ m_process_launch_info.AppendFileAction(file_action);
+ return SendOKResponse();
+ }
+ return SendErrorResponse(16);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("QSetSTDERR:"));
- FileAction file_action;
- std::string path;
- packet.GetHexByteString(path);
- const bool read = true;
- const bool write = false;
- if (file_action.Open(STDERR_FILENO, FileSpec{path, false}, read, write))
- {
- m_process_launch_info.AppendFileAction(file_action);
- return SendOKResponse ();
- }
- return SendErrorResponse (17);
+GDBRemoteCommunicationServerCommon::Handle_QSetSTDERR(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("QSetSTDERR:"));
+ FileAction file_action;
+ std::string path;
+ packet.GetHexByteString(path);
+ const bool read = false;
+ const bool write = true;
+ if (file_action.Open(STDERR_FILENO, FileSpec{path, false}, read, write)) {
+ m_process_launch_info.AppendFileAction(file_action);
+ return SendOKResponse();
+ }
+ return SendErrorResponse(17);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess (StringExtractorGDBRemote &packet)
-{
- if (m_process_launch_error.Success())
- return SendOKResponse();
- StreamString response;
- response.PutChar('E');
- response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
- return SendPacketNoLock (response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerCommon::Handle_qLaunchSuccess(
+ StringExtractorGDBRemote &packet) {
+ if (m_process_launch_error.Success())
+ return SendOKResponse();
+ StreamString response;
+ response.PutChar('E');
+ response.PutCString(m_process_launch_error.AsCString("<unknown error>"));
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QEnvironment (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("QEnvironment:"));
- const uint32_t bytes_left = packet.GetBytesLeft();
- if (bytes_left > 0)
- {
- m_process_launch_info.GetEnvironmentEntries ().AppendArgument (packet.Peek());
- return SendOKResponse ();
- }
- return SendErrorResponse (12);
+GDBRemoteCommunicationServerCommon::Handle_QEnvironment(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("QEnvironment:"));
+ const uint32_t bytes_left = packet.GetBytesLeft();
+ if (bytes_left > 0) {
+ m_process_launch_info.GetEnvironmentEntries().AppendArgument(
+ llvm::StringRef::withNullAsEmpty(packet.Peek()));
+ return SendOKResponse();
+ }
+ return SendErrorResponse(12);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen("QEnvironmentHexEncoded:"));
- const uint32_t bytes_left = packet.GetBytesLeft();
- if (bytes_left > 0)
- {
- std::string str;
- packet.GetHexByteString(str);
- m_process_launch_info.GetEnvironmentEntries().AppendArgument(str.c_str());
- return SendOKResponse();
- }
- return SendErrorResponse(12);
+GDBRemoteCommunicationServerCommon::Handle_QEnvironmentHexEncoded(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("QEnvironmentHexEncoded:"));
+ const uint32_t bytes_left = packet.GetBytesLeft();
+ if (bytes_left > 0) {
+ std::string str;
+ packet.GetHexByteString(str);
+ m_process_launch_info.GetEnvironmentEntries().AppendArgument(str);
+ return SendOKResponse();
+ }
+ return SendErrorResponse(12);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_QLaunchArch (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("QLaunchArch:"));
- const uint32_t bytes_left = packet.GetBytesLeft();
- if (bytes_left > 0)
- {
- const char* arch_triple = packet.Peek();
- ArchSpec arch_spec(arch_triple,NULL);
- m_process_launch_info.SetArchitecture(arch_spec);
- return SendOKResponse();
- }
- return SendErrorResponse(13);
+GDBRemoteCommunicationServerCommon::Handle_QLaunchArch(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("QLaunchArch:"));
+ const uint32_t bytes_left = packet.GetBytesLeft();
+ if (bytes_left > 0) {
+ const char *arch_triple = packet.Peek();
+ ArchSpec arch_spec(arch_triple, NULL);
+ m_process_launch_info.SetArchitecture(arch_spec);
+ return SendOKResponse();
+ }
+ return SendErrorResponse(13);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_A (StringExtractorGDBRemote &packet)
-{
- // The 'A' packet is the most over designed packet ever here with
- // redundant argument indexes, redundant argument lengths and needed hex
- // encoded argument string values. Really all that is needed is a comma
- // separated hex encoded argument value list, but we will stay true to the
- // documented version of the 'A' packet here...
-
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- int actual_arg_index = 0;
-
- packet.SetFilePos(1); // Skip the 'A'
- bool success = true;
- while (success && packet.GetBytesLeft() > 0)
- {
- // Decode the decimal argument string length. This length is the
- // number of hex nibbles in the argument string value.
- const uint32_t arg_len = packet.GetU32(UINT32_MAX);
- if (arg_len == UINT32_MAX)
+GDBRemoteCommunicationServerCommon::Handle_A(StringExtractorGDBRemote &packet) {
+ // The 'A' packet is the most over designed packet ever here with
+ // redundant argument indexes, redundant argument lengths and needed hex
+ // encoded argument string values. Really all that is needed is a comma
+ // separated hex encoded argument value list, but we will stay true to the
+ // documented version of the 'A' packet here...
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ int actual_arg_index = 0;
+
+ packet.SetFilePos(1); // Skip the 'A'
+ bool success = true;
+ while (success && packet.GetBytesLeft() > 0) {
+ // Decode the decimal argument string length. This length is the
+ // number of hex nibbles in the argument string value.
+ const uint32_t arg_len = packet.GetU32(UINT32_MAX);
+ if (arg_len == UINT32_MAX)
+ success = false;
+ else {
+ // Make sure the argument hex string length is followed by a comma
+ if (packet.GetChar() != ',')
+ success = false;
+ else {
+ // Decode the argument index. We ignore this really because
+ // who would really send down the arguments in a random order???
+ const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
+ if (arg_idx == UINT32_MAX)
+ success = false;
+ else {
+ // Make sure the argument index is followed by a comma
+ if (packet.GetChar() != ',')
success = false;
- else
- {
- // Make sure the argument hex string length is followed by a comma
- if (packet.GetChar() != ',')
- success = false;
- else
- {
- // Decode the argument index. We ignore this really because
- // who would really send down the arguments in a random order???
- const uint32_t arg_idx = packet.GetU32(UINT32_MAX);
- if (arg_idx == UINT32_MAX)
- success = false;
- else
- {
- // Make sure the argument index is followed by a comma
- if (packet.GetChar() != ',')
- success = false;
- else
- {
- // Decode the argument string value from hex bytes
- // back into a UTF8 string and make sure the length
- // matches the one supplied in the packet
- std::string arg;
- if (packet.GetHexByteStringFixedLength(arg, arg_len) != (arg_len / 2))
- success = false;
- else
- {
- // If there are any bytes left
- if (packet.GetBytesLeft())
- {
- if (packet.GetChar() != ',')
- success = false;
- }
-
- if (success)
- {
- if (arg_idx == 0)
- m_process_launch_info.GetExecutableFile().SetFile(arg.c_str(), false);
- m_process_launch_info.GetArguments().AppendArgument(arg.c_str());
- if (log)
- log->Printf ("LLGSPacketHandler::%s added arg %d: \"%s\"", __FUNCTION__, actual_arg_index, arg.c_str ());
- ++actual_arg_index;
- }
- }
- }
- }
+ else {
+ // Decode the argument string value from hex bytes
+ // back into a UTF8 string and make sure the length
+ // matches the one supplied in the packet
+ std::string arg;
+ if (packet.GetHexByteStringFixedLength(arg, arg_len) !=
+ (arg_len / 2))
+ success = false;
+ else {
+ // If there are any bytes left
+ if (packet.GetBytesLeft()) {
+ if (packet.GetChar() != ',')
+ success = false;
+ }
+
+ if (success) {
+ if (arg_idx == 0)
+ m_process_launch_info.GetExecutableFile().SetFile(arg, false);
+ m_process_launch_info.GetArguments().AppendArgument(arg);
+ if (log)
+ log->Printf("LLGSPacketHandler::%s added arg %d: \"%s\"",
+ __FUNCTION__, actual_arg_index, arg.c_str());
+ ++actual_arg_index;
+ }
}
+ }
}
+ }
}
-
- if (success)
- {
- m_process_launch_error = LaunchProcess ();
- if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID)
- {
- return SendOKResponse ();
- }
- else
- {
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf("LLGSPacketHandler::%s failed to launch exe: %s",
- __FUNCTION__,
- m_process_launch_error.AsCString());
-
- }
+ }
+
+ if (success) {
+ m_process_launch_error = LaunchProcess();
+ if (m_process_launch_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) {
+ return SendOKResponse();
+ } else {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("LLGSPacketHandler::%s failed to launch exe: %s",
+ __FUNCTION__, m_process_launch_error.AsCString());
}
- return SendErrorResponse (8);
+ }
+ return SendErrorResponse(8);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qEcho (StringExtractorGDBRemote &packet)
-{
- // Just echo back the exact same packet for qEcho...
- return SendPacketNoLock(packet.GetStringRef().c_str(), packet.GetStringRef().size());
+GDBRemoteCommunicationServerCommon::Handle_qEcho(
+ StringExtractorGDBRemote &packet) {
+ // Just echo back the exact same packet for qEcho...
+ return SendPacketNoLock(packet.GetStringRef());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerCommon::Handle_qModuleInfo (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("qModuleInfo:"));
-
- std::string module_path;
- packet.GetHexByteStringTerminatedBy(module_path, ';');
- if (module_path.empty())
- return SendErrorResponse (1);
-
- if (packet.GetChar() != ';')
- return SendErrorResponse (2);
-
- std::string triple;
- packet.GetHexByteString(triple);
- ArchSpec arch(triple.c_str());
-
- const FileSpec req_module_path_spec(module_path.c_str(), true);
- const FileSpec module_path_spec = FindModuleFile(req_module_path_spec.GetPath(), arch);
- const ModuleSpec module_spec(module_path_spec, arch);
-
- ModuleSpecList module_specs;
- if (!ObjectFile::GetModuleSpecifications(module_path_spec, 0, 0, module_specs))
- return SendErrorResponse (3);
+GDBRemoteCommunicationServerCommon::Handle_qModuleInfo(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("qModuleInfo:"));
+
+ std::string module_path;
+ packet.GetHexByteStringTerminatedBy(module_path, ';');
+ if (module_path.empty())
+ return SendErrorResponse(1);
+
+ if (packet.GetChar() != ';')
+ return SendErrorResponse(2);
+
+ std::string triple;
+ packet.GetHexByteString(triple);
+
+ ModuleSpec matched_module_spec = GetModuleInfo(module_path, triple);
+ if (!matched_module_spec.GetFileSpec())
+ return SendErrorResponse(3);
+
+ const auto file_offset = matched_module_spec.GetObjectOffset();
+ const auto file_size = matched_module_spec.GetObjectSize();
+ const auto uuid_str = matched_module_spec.GetUUID().GetAsString("");
+
+ StreamGDBRemote response;
+
+ if (uuid_str.empty()) {
+ std::string md5_hash;
+ if (!FileSystem::CalculateMD5AsString(matched_module_spec.GetFileSpec(),
+ file_offset, file_size, md5_hash))
+ return SendErrorResponse(5);
+ response.PutCString("md5:");
+ response.PutCStringAsRawHex8(md5_hash.c_str());
+ } else {
+ response.PutCString("uuid:");
+ response.PutCStringAsRawHex8(uuid_str.c_str());
+ }
+ response.PutChar(';');
+
+ const auto &module_arch = matched_module_spec.GetArchitecture();
+ response.PutCString("triple:");
+ response.PutCStringAsRawHex8(module_arch.GetTriple().getTriple().c_str());
+ response.PutChar(';');
+
+ response.PutCString("file_path:");
+ response.PutCStringAsRawHex8(matched_module_spec.GetFileSpec().GetCString());
+ response.PutChar(';');
+ response.PutCString("file_offset:");
+ response.PutHex64(file_offset);
+ response.PutChar(';');
+ response.PutCString("file_size:");
+ response.PutHex64(file_size);
+ response.PutChar(';');
+
+ return SendPacketNoLock(response.GetString());
+}
- ModuleSpec matched_module_spec;
- if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
- return SendErrorResponse (4);
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerCommon::Handle_jModulesInfo(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("jModulesInfo:"));
+
+ StructuredData::ObjectSP object_sp = StructuredData::ParseJSON(packet.Peek());
+ if (!object_sp)
+ return SendErrorResponse(1);
+
+ StructuredData::Array *packet_array = object_sp->GetAsArray();
+ if (!packet_array)
+ return SendErrorResponse(2);
+
+ JSONArray::SP response_array_sp = std::make_shared<JSONArray>();
+ for (size_t i = 0; i < packet_array->GetSize(); ++i) {
+ StructuredData::Dictionary *query =
+ packet_array->GetItemAtIndex(i)->GetAsDictionary();
+ if (!query)
+ continue;
+ std::string file, triple;
+ if (!query->GetValueForKeyAsString("file", file) ||
+ !query->GetValueForKeyAsString("triple", triple))
+ continue;
+
+ ModuleSpec matched_module_spec = GetModuleInfo(file, triple);
+ if (!matched_module_spec.GetFileSpec())
+ continue;
const auto file_offset = matched_module_spec.GetObjectOffset();
const auto file_size = matched_module_spec.GetObjectSize();
const auto uuid_str = matched_module_spec.GetUUID().GetAsString("");
- StreamGDBRemote response;
-
if (uuid_str.empty())
- {
- std::string md5_hash;
- if (!FileSystem::CalculateMD5AsString(matched_module_spec.GetFileSpec(), file_offset, file_size, md5_hash))
- return SendErrorResponse (5);
- response.PutCString ("md5:");
- response.PutCStringAsRawHex8(md5_hash.c_str());
- }
- else{
- response.PutCString ("uuid:");
- response.PutCStringAsRawHex8(uuid_str.c_str());
- }
- response.PutChar(';');
+ continue;
+
+ JSONObject::SP response = std::make_shared<JSONObject>();
+ response_array_sp->AppendObject(response);
+ response->SetObject("uuid", std::make_shared<JSONString>(uuid_str));
+ response->SetObject(
+ "triple",
+ std::make_shared<JSONString>(
+ matched_module_spec.GetArchitecture().GetTriple().getTriple()));
+ response->SetObject("file_path",
+ std::make_shared<JSONString>(
+ matched_module_spec.GetFileSpec().GetPath()));
+ response->SetObject("file_offset",
+ std::make_shared<JSONNumber>(file_offset));
+ response->SetObject("file_size", std::make_shared<JSONNumber>(file_size));
+ }
+
+ StreamString response;
+ response_array_sp->Write(response);
+ StreamGDBRemote escaped_response;
+ escaped_response.PutEscapedBytes(response.GetString().data(),
+ response.GetSize());
+ return SendPacketNoLock(escaped_response.GetString());
+}
- const auto &module_arch = matched_module_spec.GetArchitecture();
+void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse(
+ const ProcessInstanceInfo &proc_info, StreamString &response) {
+ response.Printf(
+ "pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
+ proc_info.GetProcessID(), proc_info.GetParentProcessID(),
+ proc_info.GetUserID(), proc_info.GetGroupID(),
+ proc_info.GetEffectiveUserID(), proc_info.GetEffectiveGroupID());
+ response.PutCString("name:");
+ response.PutCStringAsRawHex8(proc_info.GetExecutableFile().GetCString());
+ response.PutChar(';');
+ const ArchSpec &proc_arch = proc_info.GetArchitecture();
+ if (proc_arch.IsValid()) {
+ const llvm::Triple &proc_triple = proc_arch.GetTriple();
response.PutCString("triple:");
- response.PutCStringAsRawHex8( module_arch.GetTriple().getTriple().c_str());
- response.PutChar(';');
-
- response.PutCString("file_path:");
- response.PutCStringAsRawHex8(module_path_spec.GetCString());
- response.PutChar(';');
- response.PutCString("file_offset:");
- response.PutHex64(file_offset);
+ response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
response.PutChar(';');
- response.PutCString("file_size:");
- response.PutHex64(file_size);
- response.PutChar(';');
-
- return SendPacketNoLock(response.GetData(), response.GetSize());
+ }
}
-void
-GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info,
- StreamString &response)
-{
- response.Printf ("pid:%" PRIu64 ";ppid:%" PRIu64 ";uid:%i;gid:%i;euid:%i;egid:%i;",
- proc_info.GetProcessID(),
- proc_info.GetParentProcessID(),
- proc_info.GetUserID(),
- proc_info.GetGroupID(),
- proc_info.GetEffectiveUserID(),
- proc_info.GetEffectiveGroupID());
- response.PutCString ("name:");
- response.PutCStringAsRawHex8(proc_info.GetExecutableFile().GetCString());
+void GDBRemoteCommunicationServerCommon::
+ CreateProcessInfoResponse_DebugServerStyle(
+ const ProcessInstanceInfo &proc_info, StreamString &response) {
+ response.Printf("pid:%" PRIx64 ";parent-pid:%" PRIx64
+ ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;",
+ proc_info.GetProcessID(), proc_info.GetParentProcessID(),
+ proc_info.GetUserID(), proc_info.GetGroupID(),
+ proc_info.GetEffectiveUserID(),
+ proc_info.GetEffectiveGroupID());
+
+ const ArchSpec &proc_arch = proc_info.GetArchitecture();
+ if (proc_arch.IsValid()) {
+ const llvm::Triple &proc_triple = proc_arch.GetTriple();
+#if defined(__APPLE__)
+ // We'll send cputype/cpusubtype.
+ const uint32_t cpu_type = proc_arch.GetMachOCPUType();
+ if (cpu_type != 0)
+ response.Printf("cputype:%" PRIx32 ";", cpu_type);
+
+ const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType();
+ if (cpu_subtype != 0)
+ response.Printf("cpusubtype:%" PRIx32 ";", cpu_subtype);
+
+ const std::string vendor = proc_triple.getVendorName();
+ if (!vendor.empty())
+ response.Printf("vendor:%s;", vendor.c_str());
+#else
+ // We'll send the triple.
+ response.PutCString("triple:");
+ response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
response.PutChar(';');
- const ArchSpec &proc_arch = proc_info.GetArchitecture();
- if (proc_arch.IsValid())
- {
- const llvm::Triple &proc_triple = proc_arch.GetTriple();
- response.PutCString("triple:");
- response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
- response.PutChar(';');
+#endif
+ std::string ostype = proc_triple.getOSName();
+ // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64.
+ if (proc_triple.getVendor() == llvm::Triple::Apple) {
+ switch (proc_triple.getArch()) {
+ case llvm::Triple::arm:
+ case llvm::Triple::thumb:
+ case llvm::Triple::aarch64:
+ ostype = "ios";
+ break;
+ default:
+ // No change.
+ break;
+ }
+ }
+ response.Printf("ostype:%s;", ostype.c_str());
+
+ switch (proc_arch.GetByteOrder()) {
+ case lldb::eByteOrderLittle:
+ response.PutCString("endian:little;");
+ break;
+ case lldb::eByteOrderBig:
+ response.PutCString("endian:big;");
+ break;
+ case lldb::eByteOrderPDP:
+ response.PutCString("endian:pdp;");
+ break;
+ default:
+ // Nothing.
+ break;
}
+ // In case of MIPS64, pointer size is depend on ELF ABI
+ // For N32 the pointer size is 4 and for N64 it is 8
+ std::string abi = proc_arch.GetTargetABI();
+ if (!abi.empty())
+ response.Printf("elf_abi:%s;", abi.c_str());
+ response.Printf("ptrsize:%d;", proc_arch.GetAddressByteSize());
+ }
}
-void
-GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse_DebugServerStyle (
- const ProcessInstanceInfo &proc_info, StreamString &response)
-{
- response.Printf ("pid:%" PRIx64 ";parent-pid:%" PRIx64 ";real-uid:%x;real-gid:%x;effective-uid:%x;effective-gid:%x;",
- proc_info.GetProcessID(),
- proc_info.GetParentProcessID(),
- proc_info.GetUserID(),
- proc_info.GetGroupID(),
- proc_info.GetEffectiveUserID(),
- proc_info.GetEffectiveGroupID());
-
- const ArchSpec &proc_arch = proc_info.GetArchitecture();
- if (proc_arch.IsValid())
- {
- const llvm::Triple &proc_triple = proc_arch.GetTriple();
-#if defined(__APPLE__)
- // We'll send cputype/cpusubtype.
- const uint32_t cpu_type = proc_arch.GetMachOCPUType();
- if (cpu_type != 0)
- response.Printf ("cputype:%" PRIx32 ";", cpu_type);
-
- const uint32_t cpu_subtype = proc_arch.GetMachOCPUSubType();
- if (cpu_subtype != 0)
- response.Printf ("cpusubtype:%" PRIx32 ";", cpu_subtype);
-
- const std::string vendor = proc_triple.getVendorName ();
- if (!vendor.empty ())
- response.Printf ("vendor:%s;", vendor.c_str ());
+FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile(
+ const std::string &module_path, const ArchSpec &arch) {
+#ifdef __ANDROID__
+ return HostInfoAndroid::ResolveLibraryPath(module_path, arch);
#else
- // We'll send the triple.
- response.PutCString("triple:");
- response.PutCStringAsRawHex8(proc_triple.getTriple().c_str());
- response.PutChar(';');
+ return FileSpec(module_path, true);
#endif
- std::string ostype = proc_triple.getOSName ();
- // Adjust so ostype reports ios for Apple/ARM and Apple/ARM64.
- if (proc_triple.getVendor () == llvm::Triple::Apple)
- {
- switch (proc_triple.getArch ())
- {
- case llvm::Triple::arm:
- case llvm::Triple::thumb:
- case llvm::Triple::aarch64:
- ostype = "ios";
- break;
- default:
- // No change.
- break;
- }
- }
- response.Printf ("ostype:%s;", ostype.c_str ());
+}
+ModuleSpec GDBRemoteCommunicationServerCommon::GetModuleInfo(
+ const std::string &module_path, const std::string &triple) {
+ ArchSpec arch(triple.c_str());
- switch (proc_arch.GetByteOrder ())
- {
- case lldb::eByteOrderLittle: response.PutCString ("endian:little;"); break;
- case lldb::eByteOrderBig: response.PutCString ("endian:big;"); break;
- case lldb::eByteOrderPDP: response.PutCString ("endian:pdp;"); break;
- default:
- // Nothing.
- break;
- }
+ const FileSpec req_module_path_spec(module_path, true);
+ const FileSpec module_path_spec =
+ FindModuleFile(req_module_path_spec.GetPath(), arch);
+ const ModuleSpec module_spec(module_path_spec, arch);
- // In case of MIPS64, pointer size is depend on ELF ABI
- // For N32 the pointer size is 4 and for N64 it is 8
- std::string abi = proc_arch.GetTargetABI();
- if (!abi.empty())
- response.Printf("elf_abi:%s;", abi.c_str());
- response.Printf("ptrsize:%d;", proc_arch.GetAddressByteSize());
- }
-}
+ ModuleSpecList module_specs;
+ if (!ObjectFile::GetModuleSpecifications(module_path_spec, 0, 0,
+ module_specs))
+ return ModuleSpec();
-FileSpec
-GDBRemoteCommunicationServerCommon::FindModuleFile(const std::string& module_path,
- const ArchSpec& arch)
-{
-#ifdef __ANDROID__
- return HostInfoAndroid::ResolveLibraryPath(module_path, arch);
-#else
- return FileSpec(module_path.c_str(), true);
-#endif
+ ModuleSpec matched_module_spec;
+ if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec))
+ return ModuleSpec();
+
+ return matched_module_spec;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
index d2fd700..321a922 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h
@@ -16,8 +16,8 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private-forward.h"
#include "lldb/Target/Process.h"
+#include "lldb/lldb-private-forward.h"
#include "GDBRemoteCommunicationServer.h"
#include "GDBRemoteCommunicationServerCommon.h"
@@ -29,175 +29,132 @@ namespace process_gdb_remote {
class ProcessGDBRemote;
-class GDBRemoteCommunicationServerCommon :
- public GDBRemoteCommunicationServer
-{
+class GDBRemoteCommunicationServerCommon : public GDBRemoteCommunicationServer {
public:
- GDBRemoteCommunicationServerCommon(const char *comm_name, const char *listener_name);
+ GDBRemoteCommunicationServerCommon(const char *comm_name,
+ const char *listener_name);
- ~GDBRemoteCommunicationServerCommon() override;
+ ~GDBRemoteCommunicationServerCommon() override;
protected:
- ProcessLaunchInfo m_process_launch_info;
- Error m_process_launch_error;
- ProcessInstanceInfoList m_proc_infos;
- uint32_t m_proc_infos_index;
- bool m_thread_suffix_supported;
- bool m_list_threads_in_stop_reply;
+ ProcessLaunchInfo m_process_launch_info;
+ Error m_process_launch_error;
+ ProcessInstanceInfoList m_proc_infos;
+ uint32_t m_proc_infos_index;
+ bool m_thread_suffix_supported;
+ bool m_list_threads_in_stop_reply;
+
+ PacketResult Handle_A(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_A (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qHostInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qHostInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qProcessInfoPID(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qfProcessInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qfProcessInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qsProcessInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qsProcessInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qUserName(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qUserName (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qGroupName(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qGroupName (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qSpeedTest(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qSpeedTest (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_Open(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_Open (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_Close(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_Close (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_pRead(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_pRead (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_pWrite(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_pWrite (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_Size(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_Size (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_Mode(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_Mode (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_Exists(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_Exists (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_symlink(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_symlink (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_unlink(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_unlink (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_Stat(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_Stat (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vFile_MD5(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vFile_MD5 (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qEcho(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qEcho (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qModuleInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qModuleInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_jModulesInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qPlatform_shell (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qPlatform_shell(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qPlatform_mkdir (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qPlatform_mkdir(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qPlatform_chmod (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qPlatform_chmod(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qSupported (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qSupported(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QThreadSuffixSupported(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QListThreadsInStopReply(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QSetDetachOnError (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QSetDetachOnError(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QStartNoAckMode (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QStartNoAckMode(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QSetSTDIN (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QSetSTDIN(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QSetSTDOUT (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QSetSTDOUT(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QSetSTDERR(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qLaunchSuccess (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qLaunchSuccess(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QEnvironment (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QEnvironment(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QEnvironmentHexEncoded (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QEnvironmentHexEncoded(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QLaunchArch (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QLaunchArch(StringExtractorGDBRemote &packet);
- static void
- CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info,
- StreamString &response);
+ static void CreateProcessInfoResponse(const ProcessInstanceInfo &proc_info,
+ StreamString &response);
- static void
- CreateProcessInfoResponse_DebugServerStyle (const ProcessInstanceInfo &proc_info,
- StreamString &response);
+ static void CreateProcessInfoResponse_DebugServerStyle(
+ const ProcessInstanceInfo &proc_info, StreamString &response);
- template <typename T>
- void
- RegisterMemberFunctionHandler (StringExtractorGDBRemote::ServerPacketType packet_type,
- PacketResult (T::*handler) (StringExtractorGDBRemote& packet))
- {
- RegisterPacketHandler(packet_type,
- [this, handler] (StringExtractorGDBRemote packet,
- Error &error,
- bool &interrupt,
- bool &quit)
- {
- return (static_cast<T*>(this)->*handler) (packet);
- });
- }
+ template <typename T>
+ void RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::ServerPacketType packet_type,
+ PacketResult (T::*handler)(StringExtractorGDBRemote &packet)) {
+ RegisterPacketHandler(packet_type,
+ [this, handler](StringExtractorGDBRemote packet,
+ Error &error, bool &interrupt,
+ bool &quit) {
+ return (static_cast<T *>(this)->*handler)(packet);
+ });
+ }
- bool
- GetThreadSuffixSupported () override
- {
- return true;
- }
+ //------------------------------------------------------------------
+ /// Launch a process with the current launch settings.
+ ///
+ /// This method supports running an lldb-gdbserver or similar
+ /// server in a situation where the startup code has been provided
+ /// with all the information for a child process to be launched.
+ ///
+ /// @return
+ /// An Error object indicating the success or failure of the
+ /// launch.
+ //------------------------------------------------------------------
+ virtual Error LaunchProcess() = 0;
- //------------------------------------------------------------------
- /// Launch a process with the current launch settings.
- ///
- /// This method supports running an lldb-gdbserver or similar
- /// server in a situation where the startup code has been provided
- /// with all the information for a child process to be launched.
- ///
- /// @return
- /// An Error object indicating the success or failure of the
- /// launch.
- //------------------------------------------------------------------
- virtual Error
- LaunchProcess () = 0;
+ virtual FileSpec FindModuleFile(const std::string &module_path,
+ const ArchSpec &arch);
- virtual FileSpec
- FindModuleFile (const std::string& module_path, const ArchSpec& arch);
+private:
+ ModuleSpec GetModuleInfo(const std::string &module_path,
+ const std::string &triple);
};
} // namespace process_gdb_remote
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
index c468ba3..bf72673 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -16,13 +16,11 @@
// C Includes
// C++ Includes
-#include <cstring>
#include <chrono>
+#include <cstring>
#include <thread>
// Other libraries and framework includes
-#include "llvm/ADT/Triple.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Core/DataBuffer.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/RegisterValue.h"
@@ -36,20 +34,22 @@
#include "lldb/Host/Host.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
-#include "lldb/Host/TimeValue.h"
-#include "lldb/Target/FileAction.h"
-#include "lldb/Target/MemoryRegionInfo.h"
-#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "lldb/Host/common/NativeRegisterContext.h"
#include "lldb/Host/common/NativeThreadProtocol.h"
+#include "lldb/Interpreter/Args.h"
+#include "lldb/Target/FileAction.h"
+#include "lldb/Target/MemoryRegionInfo.h"
#include "lldb/Utility/JSON.h"
#include "lldb/Utility/LLDBAssert.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Support/ScopedPrinter.h"
// Project includes
-#include "Utility/StringExtractorGDBRemote.h"
-#include "Utility/UriParser.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
+#include "Utility/StringExtractorGDBRemote.h"
+#include "Utility/UriParser.h"
using namespace lldb;
using namespace lldb_private;
@@ -60,2934 +60,3110 @@ using namespace llvm;
// GDBRemote Errors
//----------------------------------------------------------------------
-namespace
-{
- enum GDBRemoteServerError
- {
- // Set to the first unused error number in literal form below
- eErrorFirst = 29,
- eErrorNoProcess = eErrorFirst,
- eErrorResume,
- eErrorExitStatus
- };
+namespace {
+enum GDBRemoteServerError {
+ // Set to the first unused error number in literal form below
+ eErrorFirst = 29,
+ eErrorNoProcess = eErrorFirst,
+ eErrorResume,
+ eErrorExitStatus
+};
}
//----------------------------------------------------------------------
// GDBRemoteCommunicationServerLLGS constructor
//----------------------------------------------------------------------
-GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(MainLoop &mainloop)
- : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"),
- m_mainloop(mainloop),
- m_current_tid(LLDB_INVALID_THREAD_ID),
- m_continue_tid(LLDB_INVALID_THREAD_ID),
- m_debugged_process_mutex(),
- m_debugged_process_sp(),
- m_stdio_communication("process.stdio"),
+GDBRemoteCommunicationServerLLGS::GDBRemoteCommunicationServerLLGS(
+ MainLoop &mainloop)
+ : GDBRemoteCommunicationServerCommon("gdb-remote.server",
+ "gdb-remote.server.rx_packet"),
+ m_mainloop(mainloop), m_current_tid(LLDB_INVALID_THREAD_ID),
+ m_continue_tid(LLDB_INVALID_THREAD_ID), m_debugged_process_mutex(),
+ m_debugged_process_sp(), m_stdio_communication("process.stdio"),
m_inferior_prev_state(StateType::eStateInvalid),
- m_active_auxv_buffer_sp(),
- m_saved_registers_mutex(),
- m_saved_registers_map(),
- m_next_saved_registers_id(1),
- m_handshake_completed(false)
-{
- RegisterPacketHandlers();
-}
-
-void
-GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers()
-{
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C,
- &GDBRemoteCommunicationServerLLGS::Handle_C);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c,
- &GDBRemoteCommunicationServerLLGS::Handle_c);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D,
- &GDBRemoteCommunicationServerLLGS::Handle_D);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H,
- &GDBRemoteCommunicationServerLLGS::Handle_H);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I,
- &GDBRemoteCommunicationServerLLGS::Handle_I);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
- &GDBRemoteCommunicationServerLLGS::Handle_interrupt);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_m,
- &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M,
- &GDBRemoteCommunicationServerLLGS::Handle_M);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p,
- &GDBRemoteCommunicationServerLLGS::Handle_p);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P,
- &GDBRemoteCommunicationServerLLGS::Handle_P);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
- &GDBRemoteCommunicationServerLLGS::Handle_qC);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qfThreadInfo,
- &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress,
- &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
- &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo,
- &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported,
- &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
- &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qRegisterInfo,
- &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState,
- &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState,
- &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR,
- &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
- &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qsThreadInfo,
- &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo,
- &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jThreadsInfo,
- &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo,
- &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read,
- &GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s,
- &GDBRemoteCommunicationServerLLGS::Handle_s);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_stop_reason,
- &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ?
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vAttach,
- &GDBRemoteCommunicationServerLLGS::Handle_vAttach);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vCont,
- &GDBRemoteCommunicationServerLLGS::Handle_vCont);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_vCont_actions,
- &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_x,
- &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z,
- &GDBRemoteCommunicationServerLLGS::Handle_Z);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z,
- &GDBRemoteCommunicationServerLLGS::Handle_z);
-
- RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
- [this](StringExtractorGDBRemote packet,
- Error &error,
- bool &interrupt,
- bool &quit)
- {
- quit = true;
- return this->Handle_k (packet);
- });
-}
-
-Error
-GDBRemoteCommunicationServerLLGS::SetLaunchArguments (const char *const args[], int argc)
-{
- if ((argc < 1) || !args || !args[0] || !args[0][0])
- return Error ("%s: no process command line specified to launch", __FUNCTION__);
-
- m_process_launch_info.SetArguments (const_cast<const char**> (args), true);
- return Error ();
-}
-
-Error
-GDBRemoteCommunicationServerLLGS::SetLaunchFlags (unsigned int launch_flags)
-{
- m_process_launch_info.GetFlags ().Set (launch_flags);
- return Error ();
-}
-
-Error
-GDBRemoteCommunicationServerLLGS::LaunchProcess ()
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
- return Error ("%s: no process command line specified to launch", __FUNCTION__);
-
- Error error;
- {
- std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
- assert (!m_debugged_process_sp && "lldb-gdbserver creating debugged process but one already exists");
- error = NativeProcessProtocol::Launch(
- m_process_launch_info,
- *this,
- m_mainloop,
- m_debugged_process_sp);
- }
-
- if (!error.Success ())
- {
- fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
- return error;
- }
-
- // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol
- // as needed.
- // llgs local-process debugging may specify PTY paths, which will make these
- // file actions non-null
- // process launch -i/e/o will also make these file actions non-null
- // nullptr means that the traffic is expected to flow over gdb-remote protocol
- if (
- m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr ||
- m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
- m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr
- )
- {
- // nullptr means it's not redirected to file or pty (in case of LLGS local)
- // at least one of stdio will be transferred pty<->gdb-remote
- // we need to give the pty master handle to this object to read and/or write
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " setting up stdout/stderr redirection via $O gdb-remote commands", __FUNCTION__, m_debugged_process_sp->GetID ());
-
- // Setup stdout/stderr mapping from inferior to $O
- auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor ();
- if (terminal_fd >= 0)
- {
- if (log)
- log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd);
- error = SetSTDIOFileDescriptor (terminal_fd);
- if (error.Fail ())
- return error;
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd);
- }
- }
- else
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " skipping stdout/stderr redirection via $O: inferior will communicate over client-provided file descriptors", __FUNCTION__, m_debugged_process_sp->GetID ());
- }
-
- printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID ());
-
+ m_active_auxv_buffer_sp(), m_saved_registers_mutex(),
+ m_saved_registers_map(), m_next_saved_registers_id(1),
+ m_handshake_completed(false) {
+ RegisterPacketHandlers();
+}
+
+void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() {
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_C,
+ &GDBRemoteCommunicationServerLLGS::Handle_C);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_c,
+ &GDBRemoteCommunicationServerLLGS::Handle_c);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_D,
+ &GDBRemoteCommunicationServerLLGS::Handle_D);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_H,
+ &GDBRemoteCommunicationServerLLGS::Handle_H);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_I,
+ &GDBRemoteCommunicationServerLLGS::Handle_I);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_interrupt,
+ &GDBRemoteCommunicationServerLLGS::Handle_interrupt);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_m,
+ &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_M,
+ &GDBRemoteCommunicationServerLLGS::Handle_M);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_p,
+ &GDBRemoteCommunicationServerLLGS::Handle_p);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_P,
+ &GDBRemoteCommunicationServerLLGS::Handle_P);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
+ &GDBRemoteCommunicationServerLLGS::Handle_qC);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qfThreadInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qFileLoadAddress,
+ &GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
+ &GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qMemoryRegionInfoSupported,
+ &GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qRegisterInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState,
+ &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QSaveRegisterState,
+ &GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QSetDisableASLR,
+ &GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
+ &GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qsThreadInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qThreadStopInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jThreadsInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qWatchpointSupportInfo,
+ &GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qXfer_auxv_read,
+ &GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_s,
+ &GDBRemoteCommunicationServerLLGS::Handle_s);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_stop_reason,
+ &GDBRemoteCommunicationServerLLGS::Handle_stop_reason); // ?
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vAttach,
+ &GDBRemoteCommunicationServerLLGS::Handle_vAttach);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vCont,
+ &GDBRemoteCommunicationServerLLGS::Handle_vCont);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_vCont_actions,
+ &GDBRemoteCommunicationServerLLGS::Handle_vCont_actions);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_x,
+ &GDBRemoteCommunicationServerLLGS::Handle_memory_read);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_Z,
+ &GDBRemoteCommunicationServerLLGS::Handle_Z);
+ RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_z,
+ &GDBRemoteCommunicationServerLLGS::Handle_z);
+
+ RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
+ [this](StringExtractorGDBRemote packet, Error &error,
+ bool &interrupt, bool &quit) {
+ quit = true;
+ return this->Handle_k(packet);
+ });
+}
+
+Error GDBRemoteCommunicationServerLLGS::SetLaunchArguments(
+ const char *const args[], int argc) {
+ if ((argc < 1) || !args || !args[0] || !args[0][0])
+ return Error("%s: no process command line specified to launch",
+ __FUNCTION__);
+
+ m_process_launch_info.SetArguments(const_cast<const char **>(args), true);
+ return Error();
+}
+
+Error GDBRemoteCommunicationServerLLGS::SetLaunchFlags(
+ unsigned int launch_flags) {
+ m_process_launch_info.GetFlags().Set(launch_flags);
+ return Error();
+}
+
+Error GDBRemoteCommunicationServerLLGS::LaunchProcess() {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ if (!m_process_launch_info.GetArguments().GetArgumentCount())
+ return Error("%s: no process command line specified to launch",
+ __FUNCTION__);
+
+ const bool should_forward_stdio =
+ m_process_launch_info.GetFileActionForFD(STDIN_FILENO) == nullptr ||
+ m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) == nullptr ||
+ m_process_launch_info.GetFileActionForFD(STDERR_FILENO) == nullptr;
+ m_process_launch_info.SetLaunchInSeparateProcessGroup(true);
+ m_process_launch_info.GetFlags().Set(eLaunchFlagDebug);
+
+ const bool default_to_use_pty = true;
+ m_process_launch_info.FinalizeFileActions(nullptr, default_to_use_pty);
+
+ Error error;
+ {
+ std::lock_guard<std::recursive_mutex> guard(m_debugged_process_mutex);
+ assert(!m_debugged_process_sp && "lldb-server creating debugged "
+ "process but one already exists");
+ error = NativeProcessProtocol::Launch(m_process_launch_info, *this,
+ m_mainloop, m_debugged_process_sp);
+ }
+
+ if (!error.Success()) {
+ fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
+ m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
return error;
-}
-
-Error
-GDBRemoteCommunicationServerLLGS::AttachToProcess (lldb::pid_t pid)
-{
- Error error;
-
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
+ }
+
+ // Handle mirroring of inferior stdout/stderr over the gdb-remote protocol
+ // as needed.
+ // llgs local-process debugging may specify PTY paths, which will make these
+ // file actions non-null
+ // process launch -i/e/o will also make these file actions non-null
+ // nullptr means that the traffic is expected to flow over gdb-remote protocol
+ if (should_forward_stdio) {
+ // nullptr means it's not redirected to file or pty (in case of LLGS local)
+ // at least one of stdio will be transferred pty<->gdb-remote
+ // we need to give the pty master handle to this object to read and/or write
if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64, __FUNCTION__, pid);
-
- // Before we try to attach, make sure we aren't already monitoring something else.
- if (m_debugged_process_sp && m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID)
- return Error("cannot attach to a process %" PRIu64 " when another process with pid %" PRIu64 " is being debugged.", pid, m_debugged_process_sp->GetID());
-
- // Try to attach.
- error = NativeProcessProtocol::Attach(pid, *this, m_mainloop, m_debugged_process_sp);
- if (!error.Success ())
- {
- fprintf (stderr, "%s: failed to attach to process %" PRIu64 ": %s", __FUNCTION__, pid, error.AsCString ());
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " setting up stdout/stderr redirection via $O gdb-remote commands",
+ __FUNCTION__, m_debugged_process_sp->GetID());
+
+ // Setup stdout/stderr mapping from inferior to $O
+ auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor();
+ if (terminal_fd >= 0) {
+ if (log)
+ log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting "
+ "inferior STDIO fd to %d",
+ __FUNCTION__, terminal_fd);
+ error = SetSTDIOFileDescriptor(terminal_fd);
+ if (error.Fail())
return error;
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
+ "inferior STDIO since terminal fd reported as %d",
+ __FUNCTION__, terminal_fd);
}
-
- // Setup stdout/stderr mapping from inferior.
- auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor ();
- if (terminal_fd >= 0)
- {
- if (log)
- log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s setting inferior STDIO fd to %d", __FUNCTION__, terminal_fd);
- error = SetSTDIOFileDescriptor (terminal_fd);
- if (error.Fail ())
- return error;
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring inferior STDIO since terminal fd reported as %d", __FUNCTION__, terminal_fd);
- }
-
- printf ("Attached to process %" PRIu64 "...\n", pid);
-
+ } else {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " skipping stdout/stderr redirection via $O: inferior will "
+ "communicate over client-provided file descriptors",
+ __FUNCTION__, m_debugged_process_sp->GetID());
+ }
+
+ printf("Launched '%s' as process %" PRIu64 "...\n",
+ m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
+ m_process_launch_info.GetProcessID());
+
+ return error;
+}
+
+Error GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) {
+ Error error;
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64,
+ __FUNCTION__, pid);
+
+ // Before we try to attach, make sure we aren't already monitoring something
+ // else.
+ if (m_debugged_process_sp &&
+ m_debugged_process_sp->GetID() != LLDB_INVALID_PROCESS_ID)
+ return Error("cannot attach to a process %" PRIu64
+ " when another process with pid %" PRIu64
+ " is being debugged.",
+ pid, m_debugged_process_sp->GetID());
+
+ // Try to attach.
+ error = NativeProcessProtocol::Attach(pid, *this, m_mainloop,
+ m_debugged_process_sp);
+ if (!error.Success()) {
+ fprintf(stderr, "%s: failed to attach to process %" PRIu64 ": %s",
+ __FUNCTION__, pid, error.AsCString());
return error;
-}
+ }
-void
-GDBRemoteCommunicationServerLLGS::InitializeDelegate (NativeProcessProtocol *process)
-{
- assert (process && "process cannot be NULL");
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ // Setup stdout/stderr mapping from inferior.
+ auto terminal_fd = m_debugged_process_sp->GetTerminalFileDescriptor();
+ if (terminal_fd >= 0) {
if (log)
- {
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s called with NativeProcessProtocol pid %" PRIu64 ", current state: %s",
- __FUNCTION__,
- process->GetID (),
- StateAsCString (process->GetState ()));
- }
-}
-
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::SendWResponse (NativeProcessProtocol *process)
-{
- assert (process && "process cannot be NULL");
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // send W notification
- ExitType exit_type = ExitType::eExitTypeInvalid;
- int return_code = 0;
- std::string exit_description;
-
- const bool got_exit_info = process->GetExitStatus (&exit_type, &return_code, exit_description);
- if (!got_exit_info)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 ", failed to retrieve process exit status", __FUNCTION__, process->GetID ());
-
- StreamGDBRemote response;
- response.PutChar ('E');
- response.PutHex8 (GDBRemoteServerError::eErrorExitStatus);
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
- else
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 ", returning exit type %d, return code %d [%s]", __FUNCTION__, process->GetID (), exit_type, return_code, exit_description.c_str ());
-
- StreamGDBRemote response;
-
- char return_type_code;
- switch (exit_type)
- {
- case ExitType::eExitTypeExit:
- return_type_code = 'W';
- break;
- case ExitType::eExitTypeSignal:
- return_type_code = 'X';
- break;
- case ExitType::eExitTypeStop:
- return_type_code = 'S';
- break;
- case ExitType::eExitTypeInvalid:
- return_type_code = 'E';
- break;
- }
- response.PutChar (return_type_code);
+ log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s setting "
+ "inferior STDIO fd to %d",
+ __FUNCTION__, terminal_fd);
+ error = SetSTDIOFileDescriptor(terminal_fd);
+ if (error.Fail())
+ return error;
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemoteCommunicationServerLLGS::%s ignoring "
+ "inferior STDIO since terminal fd reported as %d",
+ __FUNCTION__, terminal_fd);
+ }
- // POSIX exit status limited to unsigned 8 bits.
- response.PutHex8 (return_code);
+ printf("Attached to process %" PRIu64 "...\n", pid);
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
+ return error;
}
-static void
-AppendHexValue (StreamString &response, const uint8_t* buf, uint32_t buf_size, bool swap)
-{
- int64_t i;
- if (swap)
- {
- for (i = buf_size-1; i >= 0; i--)
- response.PutHex8 (buf[i]);
- }
- else
- {
- for (i = 0; i < buf_size; i++)
- response.PutHex8 (buf[i]);
- }
+void GDBRemoteCommunicationServerLLGS::InitializeDelegate(
+ NativeProcessProtocol *process) {
+ assert(process && "process cannot be NULL");
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log) {
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s called with "
+ "NativeProcessProtocol pid %" PRIu64 ", current state: %s",
+ __FUNCTION__, process->GetID(),
+ StateAsCString(process->GetState()));
+ }
}
-static void
-WriteRegisterValueInHexFixedWidth (StreamString &response,
- NativeRegisterContextSP &reg_ctx_sp,
- const RegisterInfo &reg_info,
- const RegisterValue *reg_value_p)
-{
- RegisterValue reg_value;
- if (!reg_value_p)
- {
- Error error = reg_ctx_sp->ReadRegister (&reg_info, reg_value);
- if (error.Success ())
- reg_value_p = &reg_value;
- // else log.
- }
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::SendWResponse(
+ NativeProcessProtocol *process) {
+ assert(process && "process cannot be NULL");
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // send W notification
+ ExitType exit_type = ExitType::eExitTypeInvalid;
+ int return_code = 0;
+ std::string exit_description;
+
+ const bool got_exit_info =
+ process->GetExitStatus(&exit_type, &return_code, exit_description);
+ if (!got_exit_info) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ ", failed to retrieve process exit status",
+ __FUNCTION__, process->GetID());
- if (reg_value_p)
- {
- AppendHexValue (response, (const uint8_t*) reg_value_p->GetBytes (), reg_value_p->GetByteSize (), false);
- }
- else
- {
- // Zero-out any unreadable values.
- if (reg_info.byte_size > 0)
- {
- std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0');
- AppendHexValue (response, zeros.data(), zeros.size(), false);
- }
- }
-}
+ StreamGDBRemote response;
+ response.PutChar('E');
+ response.PutHex8(GDBRemoteServerError::eErrorExitStatus);
+ return SendPacketNoLock(response.GetString());
+ } else {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ ", returning exit type %d, return code %d [%s]",
+ __FUNCTION__, process->GetID(), exit_type, return_code,
+ exit_description.c_str());
-static JSONObject::SP
-GetRegistersAsJSON(NativeThreadProtocol &thread, bool abridged)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD));
+ StreamGDBRemote response;
- NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext ();
- if (! reg_ctx_sp)
- return nullptr;
+ char return_type_code;
+ switch (exit_type) {
+ case ExitType::eExitTypeExit:
+ return_type_code = 'W';
+ break;
+ case ExitType::eExitTypeSignal:
+ return_type_code = 'X';
+ break;
+ case ExitType::eExitTypeStop:
+ return_type_code = 'S';
+ break;
+ case ExitType::eExitTypeInvalid:
+ return_type_code = 'E';
+ break;
+ }
+ response.PutChar(return_type_code);
+
+ // POSIX exit status limited to unsigned 8 bits.
+ response.PutHex8(return_code);
+
+ return SendPacketNoLock(response.GetString());
+ }
+}
+
+static void AppendHexValue(StreamString &response, const uint8_t *buf,
+ uint32_t buf_size, bool swap) {
+ int64_t i;
+ if (swap) {
+ for (i = buf_size - 1; i >= 0; i--)
+ response.PutHex8(buf[i]);
+ } else {
+ for (i = 0; i < buf_size; i++)
+ response.PutHex8(buf[i]);
+ }
+}
+
+static void WriteRegisterValueInHexFixedWidth(
+ StreamString &response, NativeRegisterContextSP &reg_ctx_sp,
+ const RegisterInfo &reg_info, const RegisterValue *reg_value_p) {
+ RegisterValue reg_value;
+ if (!reg_value_p) {
+ Error error = reg_ctx_sp->ReadRegister(&reg_info, reg_value);
+ if (error.Success())
+ reg_value_p = &reg_value;
+ // else log.
+ }
+
+ if (reg_value_p) {
+ AppendHexValue(response, (const uint8_t *)reg_value_p->GetBytes(),
+ reg_value_p->GetByteSize(), false);
+ } else {
+ // Zero-out any unreadable values.
+ if (reg_info.byte_size > 0) {
+ std::basic_string<uint8_t> zeros(reg_info.byte_size, '\0');
+ AppendHexValue(response, zeros.data(), zeros.size(), false);
+ }
+ }
+}
+
+static JSONObject::SP GetRegistersAsJSON(NativeThreadProtocol &thread,
+ bool abridged) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ NativeRegisterContextSP reg_ctx_sp = thread.GetRegisterContext();
+ if (!reg_ctx_sp)
+ return nullptr;
- JSONObject::SP register_object_sp = std::make_shared<JSONObject>();
+ JSONObject::SP register_object_sp = std::make_shared<JSONObject>();
#ifdef LLDB_JTHREADSINFO_FULL_REGISTER_SET
- // Expedite all registers in the first register set (i.e. should be GPRs) that are not contained in other registers.
- const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0);
- if (! reg_set_p)
- return nullptr;
- for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p)
- {
- uint32_t reg_num = *reg_num_p;
+ // Expedite all registers in the first register set (i.e. should be GPRs) that
+ // are not contained in other registers.
+ const RegisterSet *reg_set_p = reg_ctx_sp->GetRegisterSet(0);
+ if (!reg_set_p)
+ return nullptr;
+ for (const uint32_t *reg_num_p = reg_set_p->registers;
+ *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) {
+ uint32_t reg_num = *reg_num_p;
#else
- // Expedite only a couple of registers until we figure out why sending registers is
- // expensive.
- static const uint32_t k_expedited_registers[] = {
- LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM
- };
- static const uint32_t k_abridged_expedited_registers[] = {
- LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM
- };
-
- for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers : k_expedited_registers;
- *generic_reg_p != LLDB_INVALID_REGNUM;
- ++generic_reg_p)
- {
- uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(eRegisterKindGeneric, *generic_reg_p);
- if (reg_num == LLDB_INVALID_REGNUM)
- continue; // Target does not support the given register.
+ // Expedite only a couple of registers until we figure out why sending
+ // registers is
+ // expensive.
+ static const uint32_t k_expedited_registers[] = {
+ LLDB_REGNUM_GENERIC_PC, LLDB_REGNUM_GENERIC_SP, LLDB_REGNUM_GENERIC_FP,
+ LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM};
+ static const uint32_t k_abridged_expedited_registers[] = {
+ LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM};
+
+ for (const uint32_t *generic_reg_p = abridged ? k_abridged_expedited_registers
+ : k_expedited_registers;
+ *generic_reg_p != LLDB_INVALID_REGNUM; ++generic_reg_p) {
+ uint32_t reg_num = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
+ eRegisterKindGeneric, *generic_reg_p);
+ if (reg_num == LLDB_INVALID_REGNUM)
+ continue; // Target does not support the given register.
#endif
- const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex(reg_num);
- if (reg_info_p == nullptr)
- {
- if (log)
- log->Printf("%s failed to get register info for register index %" PRIu32,
- __FUNCTION__, reg_num);
- continue;
- }
-
- if (reg_info_p->value_regs != nullptr)
- continue; // Only expedite registers that are not contained in other registers.
-
- RegisterValue reg_value;
- Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value);
- if (error.Fail())
- {
- if (log)
- log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__,
- reg_info_p->name ? reg_info_p->name : "<unnamed-register>", reg_num,
- error.AsCString ());
- continue;
- }
-
- StreamString stream;
- WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p, &reg_value);
-
- register_object_sp->SetObject(std::to_string(reg_num),
- std::make_shared<JSONString>(stream.GetString()));
- }
-
- return register_object_sp;
-}
-
-static const char *
-GetStopReasonString(StopReason stop_reason)
-{
- switch (stop_reason)
- {
- case eStopReasonTrace:
- return "trace";
- case eStopReasonBreakpoint:
- return "breakpoint";
- case eStopReasonWatchpoint:
- return "watchpoint";
- case eStopReasonSignal:
- return "signal";
- case eStopReasonException:
- return "exception";
- case eStopReasonExec:
- return "exec";
- case eStopReasonInstrumentation:
- case eStopReasonInvalid:
- case eStopReasonPlanComplete:
- case eStopReasonThreadExiting:
- case eStopReasonNone:
- break; // ignored
+ const RegisterInfo *const reg_info_p =
+ reg_ctx_sp->GetRegisterInfoAtIndex(reg_num);
+ if (reg_info_p == nullptr) {
+ if (log)
+ log->Printf(
+ "%s failed to get register info for register index %" PRIu32,
+ __FUNCTION__, reg_num);
+ continue;
}
- return nullptr;
-}
-static JSONArray::SP
-GetJSONThreadsInfo(NativeProcessProtocol &process, bool abridged)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ if (reg_info_p->value_regs != nullptr)
+ continue; // Only expedite registers that are not contained in other
+ // registers.
- JSONArray::SP threads_array_sp = std::make_shared<JSONArray>();
-
- // Ensure we can get info on the given thread.
- uint32_t thread_idx = 0;
- for ( NativeThreadProtocolSP thread_sp;
- (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr;
- ++thread_idx)
- {
-
- lldb::tid_t tid = thread_sp->GetID();
-
- // Grab the reason this thread stopped.
- struct ThreadStopInfo tid_stop_info;
- std::string description;
- if (!thread_sp->GetStopReason (tid_stop_info, description))
- return nullptr;
-
- const int signum = tid_stop_info.details.signal.signo;
- if (log)
- {
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
+ RegisterValue reg_value;
+ Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("%s failed to read register '%s' index %" PRIu32 ": %s",
__FUNCTION__,
- process.GetID (),
- tid,
- signum,
- tid_stop_info.reason,
- tid_stop_info.details.exception.type);
- }
-
- JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>();
- threads_array_sp->AppendObject(thread_obj_sp);
-
- if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged))
- thread_obj_sp->SetObject("registers", registers_sp);
-
- thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid));
- if (signum != 0)
- thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum));
+ reg_info_p->name ? reg_info_p->name : "<unnamed-register>",
+ reg_num, error.AsCString());
+ continue;
+ }
+
+ StreamString stream;
+ WriteRegisterValueInHexFixedWidth(stream, reg_ctx_sp, *reg_info_p,
+ &reg_value);
+
+ register_object_sp->SetObject(
+ llvm::to_string(reg_num),
+ std::make_shared<JSONString>(stream.GetString()));
+ }
+
+ return register_object_sp;
+}
+
+static const char *GetStopReasonString(StopReason stop_reason) {
+ switch (stop_reason) {
+ case eStopReasonTrace:
+ return "trace";
+ case eStopReasonBreakpoint:
+ return "breakpoint";
+ case eStopReasonWatchpoint:
+ return "watchpoint";
+ case eStopReasonSignal:
+ return "signal";
+ case eStopReasonException:
+ return "exception";
+ case eStopReasonExec:
+ return "exec";
+ case eStopReasonInstrumentation:
+ case eStopReasonInvalid:
+ case eStopReasonPlanComplete:
+ case eStopReasonThreadExiting:
+ case eStopReasonNone:
+ break; // ignored
+ }
+ return nullptr;
+}
+
+static JSONArray::SP GetJSONThreadsInfo(NativeProcessProtocol &process,
+ bool abridged) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+
+ JSONArray::SP threads_array_sp = std::make_shared<JSONArray>();
+
+ // Ensure we can get info on the given thread.
+ uint32_t thread_idx = 0;
+ for (NativeThreadProtocolSP thread_sp;
+ (thread_sp = process.GetThreadAtIndex(thread_idx)) != nullptr;
+ ++thread_idx) {
+
+ lldb::tid_t tid = thread_sp->GetID();
- const std::string thread_name = thread_sp->GetName ();
- if (! thread_name.empty())
- thread_obj_sp->SetObject("name", std::make_shared<JSONString>(thread_name));
-
- if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason))
- thread_obj_sp->SetObject("reason", std::make_shared<JSONString>(stop_reason_str));
-
- if (! description.empty())
- thread_obj_sp->SetObject("description", std::make_shared<JSONString>(description));
-
- if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type)
- {
- thread_obj_sp->SetObject("metype",
- std::make_shared<JSONNumber>(tid_stop_info.details.exception.type));
-
- JSONArray::SP medata_array_sp = std::make_shared<JSONArray>();
- for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i)
- {
- medata_array_sp->AppendObject(std::make_shared<JSONNumber>(
- tid_stop_info.details.exception.data[i]));
- }
- thread_obj_sp->SetObject("medata", medata_array_sp);
- }
+ // Grab the reason this thread stopped.
+ struct ThreadStopInfo tid_stop_info;
+ std::string description;
+ if (!thread_sp->GetStopReason(tid_stop_info, description))
+ return nullptr;
- // TODO: Expedite interesting regions of inferior memory
+ const int signum = tid_stop_info.details.signal.signo;
+ if (log) {
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " tid %" PRIu64
+ " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
+ __FUNCTION__, process.GetID(), tid, signum,
+ tid_stop_info.reason, tid_stop_info.details.exception.type);
}
- return threads_array_sp;
-}
+ JSONObject::SP thread_obj_sp = std::make_shared<JSONObject>();
+ threads_array_sp->AppendObject(thread_obj_sp);
-GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread (lldb::tid_t tid)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ if (JSONObject::SP registers_sp = GetRegistersAsJSON(*thread_sp, abridged))
+ thread_obj_sp->SetObject("registers", registers_sp);
- // Ensure we have a debugged process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse (50);
+ thread_obj_sp->SetObject("tid", std::make_shared<JSONNumber>(tid));
+ if (signum != 0)
+ thread_obj_sp->SetObject("signal", std::make_shared<JSONNumber>(signum));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64 " tid %" PRIu64,
- __FUNCTION__, m_debugged_process_sp->GetID (), tid);
+ const std::string thread_name = thread_sp->GetName();
+ if (!thread_name.empty())
+ thread_obj_sp->SetObject("name",
+ std::make_shared<JSONString>(thread_name));
- // Ensure we can get info on the given thread.
- NativeThreadProtocolSP thread_sp (m_debugged_process_sp->GetThreadByID (tid));
- if (!thread_sp)
- return SendErrorResponse (51);
+ if (const char *stop_reason_str = GetStopReasonString(tid_stop_info.reason))
+ thread_obj_sp->SetObject("reason",
+ std::make_shared<JSONString>(stop_reason_str));
- // Grab the reason this thread stopped.
- struct ThreadStopInfo tid_stop_info;
- std::string description;
- if (!thread_sp->GetStopReason (tid_stop_info, description))
- return SendErrorResponse (52);
+ if (!description.empty())
+ thread_obj_sp->SetObject("description",
+ std::make_shared<JSONString>(description));
- // FIXME implement register handling for exec'd inferiors.
- // if (tid_stop_info.reason == eStopReasonExec)
- // {
- // const bool force = true;
- // InitializeRegisters(force);
- // }
+ if ((tid_stop_info.reason == eStopReasonException) &&
+ tid_stop_info.details.exception.type) {
+ thread_obj_sp->SetObject(
+ "metype",
+ std::make_shared<JSONNumber>(tid_stop_info.details.exception.type));
- StreamString response;
- // Output the T packet with the thread
- response.PutChar ('T');
- int signum = tid_stop_info.details.signal.signo;
- if (log)
- {
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- tid,
- signum,
- tid_stop_info.reason,
- tid_stop_info.details.exception.type);
+ JSONArray::SP medata_array_sp = std::make_shared<JSONArray>();
+ for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count;
+ ++i) {
+ medata_array_sp->AppendObject(std::make_shared<JSONNumber>(
+ tid_stop_info.details.exception.data[i]));
+ }
+ thread_obj_sp->SetObject("medata", medata_array_sp);
}
- // Print the signal number.
- response.PutHex8 (signum & 0xff);
-
- // Include the tid.
- response.Printf ("thread:%" PRIx64 ";", tid);
-
- // Include the thread name if there is one.
- const std::string thread_name = thread_sp->GetName ();
- if (!thread_name.empty ())
- {
- size_t thread_name_len = thread_name.length ();
+ // TODO: Expedite interesting regions of inferior memory
+ }
- if (::strcspn (thread_name.c_str (), "$#+-;:") == thread_name_len)
- {
- response.PutCString ("name:");
- response.PutCString (thread_name.c_str ());
- }
- else
- {
- // The thread name contains special chars, send as hex bytes.
- response.PutCString ("hexname:");
- response.PutCStringAsRawHex8 (thread_name.c_str ());
- }
- response.PutChar (';');
- }
-
- // If a 'QListThreadsInStopReply' was sent to enable this feature, we
- // will send all thread IDs back in the "threads" key whose value is
- // a list of hex thread IDs separated by commas:
- // "threads:10a,10b,10c;"
- // This will save the debugger from having to send a pair of qfThreadInfo
- // and qsThreadInfo packets, but it also might take a lot of room in the
- // stop reply packet, so it must be enabled only on systems where there
- // are no limits on packet lengths.
- if (m_list_threads_in_stop_reply)
- {
- response.PutCString ("threads:");
-
- uint32_t thread_index = 0;
- NativeThreadProtocolSP listed_thread_sp;
- for (listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index); listed_thread_sp; ++thread_index, listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index))
- {
- if (thread_index > 0)
- response.PutChar (',');
- response.Printf ("%" PRIx64, listed_thread_sp->GetID ());
- }
- response.PutChar (';');
-
- // Include JSON info that describes the stop reason for any threads
- // that actually have stop reasons. We use the new "jstopinfo" key
- // whose values is hex ascii JSON that contains the thread IDs
- // thread stop info only for threads that have stop reasons. Only send
- // this if we have more than one thread otherwise this packet has all
- // the info it needs.
- if (thread_index > 0)
- {
- const bool threads_with_valid_stop_info_only = true;
- JSONArray::SP threads_info_sp = GetJSONThreadsInfo(*m_debugged_process_sp,
- threads_with_valid_stop_info_only);
- if (threads_info_sp)
- {
- response.PutCString("jstopinfo:");
- StreamString unescaped_response;
- threads_info_sp->Write(unescaped_response);
- response.PutCStringAsRawHex8(unescaped_response.GetData());
- response.PutChar(';');
- }
- else if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a jstopinfo field for pid %" PRIu64,
- __FUNCTION__, m_debugged_process_sp->GetID());
+ return threads_array_sp;
+}
- }
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::SendStopReplyPacketForThread(
+ lldb::tid_t tid) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+
+ // Ensure we have a debugged process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(50);
+
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64
+ " tid %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID(), tid);
+
+ // Ensure we can get info on the given thread.
+ NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadByID(tid));
+ if (!thread_sp)
+ return SendErrorResponse(51);
+
+ // Grab the reason this thread stopped.
+ struct ThreadStopInfo tid_stop_info;
+ std::string description;
+ if (!thread_sp->GetStopReason(tid_stop_info, description))
+ return SendErrorResponse(52);
+
+ // FIXME implement register handling for exec'd inferiors.
+ // if (tid_stop_info.reason == eStopReasonExec)
+ // {
+ // const bool force = true;
+ // InitializeRegisters(force);
+ // }
+
+ StreamString response;
+ // Output the T packet with the thread
+ response.PutChar('T');
+ int signum = tid_stop_info.details.signal.signo;
+ if (log) {
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " tid %" PRIu64
+ " got signal signo = %d, reason = %d, exc_type = %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID(), tid, signum,
+ tid_stop_info.reason, tid_stop_info.details.exception.type);
+ }
+
+ // Print the signal number.
+ response.PutHex8(signum & 0xff);
+
+ // Include the tid.
+ response.Printf("thread:%" PRIx64 ";", tid);
+
+ // Include the thread name if there is one.
+ const std::string thread_name = thread_sp->GetName();
+ if (!thread_name.empty()) {
+ size_t thread_name_len = thread_name.length();
+
+ if (::strcspn(thread_name.c_str(), "$#+-;:") == thread_name_len) {
+ response.PutCString("name:");
+ response.PutCString(thread_name);
+ } else {
+ // The thread name contains special chars, send as hex bytes.
+ response.PutCString("hexname:");
+ response.PutCStringAsRawHex8(thread_name.c_str());
+ }
+ response.PutChar(';');
+ }
+
+ // If a 'QListThreadsInStopReply' was sent to enable this feature, we
+ // will send all thread IDs back in the "threads" key whose value is
+ // a list of hex thread IDs separated by commas:
+ // "threads:10a,10b,10c;"
+ // This will save the debugger from having to send a pair of qfThreadInfo
+ // and qsThreadInfo packets, but it also might take a lot of room in the
+ // stop reply packet, so it must be enabled only on systems where there
+ // are no limits on packet lengths.
+ if (m_list_threads_in_stop_reply) {
+ response.PutCString("threads:");
+
+ uint32_t thread_index = 0;
+ NativeThreadProtocolSP listed_thread_sp;
+ for (listed_thread_sp =
+ m_debugged_process_sp->GetThreadAtIndex(thread_index);
+ listed_thread_sp; ++thread_index,
+ listed_thread_sp = m_debugged_process_sp->GetThreadAtIndex(
+ thread_index)) {
+ if (thread_index > 0)
+ response.PutChar(',');
+ response.Printf("%" PRIx64, listed_thread_sp->GetID());
+ }
+ response.PutChar(';');
+
+ // Include JSON info that describes the stop reason for any threads
+ // that actually have stop reasons. We use the new "jstopinfo" key
+ // whose values is hex ascii JSON that contains the thread IDs
+ // thread stop info only for threads that have stop reasons. Only send
+ // this if we have more than one thread otherwise this packet has all
+ // the info it needs.
+ if (thread_index > 0) {
+ const bool threads_with_valid_stop_info_only = true;
+ JSONArray::SP threads_info_sp = GetJSONThreadsInfo(
+ *m_debugged_process_sp, threads_with_valid_stop_info_only);
+ if (threads_info_sp) {
+ response.PutCString("jstopinfo:");
+ StreamString unescaped_response;
+ threads_info_sp->Write(unescaped_response);
+ response.PutCStringAsRawHex8(unescaped_response.GetData());
+ response.PutChar(';');
+ } else if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to prepare a "
+ "jstopinfo field for pid %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
}
-
- //
- // Expedite registers.
- //
-
- // Grab the register context.
- NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext ();
- if (reg_ctx_sp)
- {
- // Expedite all registers in the first register set (i.e. should be GPRs) that are not contained in other registers.
- const RegisterSet *reg_set_p;
- if (reg_ctx_sp->GetRegisterSetCount () > 0 && ((reg_set_p = reg_ctx_sp->GetRegisterSet (0)) != nullptr))
- {
+ }
+
+ //
+ // Expedite registers.
+ //
+
+ // Grab the register context.
+ NativeRegisterContextSP reg_ctx_sp = thread_sp->GetRegisterContext();
+ if (reg_ctx_sp) {
+ // Expedite all registers in the first register set (i.e. should be GPRs)
+ // that are not contained in other registers.
+ const RegisterSet *reg_set_p;
+ if (reg_ctx_sp->GetRegisterSetCount() > 0 &&
+ ((reg_set_p = reg_ctx_sp->GetRegisterSet(0)) != nullptr)) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s expediting registers "
+ "from set '%s' (registers set count: %zu)",
+ __FUNCTION__,
+ reg_set_p->name ? reg_set_p->name : "<unnamed-set>",
+ reg_set_p->num_registers);
+
+ for (const uint32_t *reg_num_p = reg_set_p->registers;
+ *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p) {
+ const RegisterInfo *const reg_info_p =
+ reg_ctx_sp->GetRegisterInfoAtIndex(*reg_num_p);
+ if (reg_info_p == nullptr) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get "
+ "register info for register set '%s', register index "
+ "%" PRIu32,
+ __FUNCTION__,
+ reg_set_p->name ? reg_set_p->name : "<unnamed-set>",
+ *reg_num_p);
+ } else if (reg_info_p->value_regs == nullptr) {
+ // Only expediate registers that are not contained in other registers.
+ RegisterValue reg_value;
+ Error error = reg_ctx_sp->ReadRegister(reg_info_p, reg_value);
+ if (error.Success()) {
+ response.Printf("%.02x:", *reg_num_p);
+ WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p,
+ &reg_value);
+ response.PutChar(';');
+ } else {
if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s expediting registers from set '%s' (registers set count: %zu)", __FUNCTION__, reg_set_p->name ? reg_set_p->name : "<unnamed-set>", reg_set_p->num_registers);
-
- for (const uint32_t *reg_num_p = reg_set_p->registers; *reg_num_p != LLDB_INVALID_REGNUM; ++reg_num_p)
- {
- const RegisterInfo *const reg_info_p = reg_ctx_sp->GetRegisterInfoAtIndex (*reg_num_p);
- if (reg_info_p == nullptr)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to get register info for register set '%s', register index %" PRIu32, __FUNCTION__, reg_set_p->name ? reg_set_p->name : "<unnamed-set>", *reg_num_p);
- }
- else if (reg_info_p->value_regs == nullptr)
- {
- // Only expediate registers that are not contained in other registers.
- RegisterValue reg_value;
- Error error = reg_ctx_sp->ReadRegister (reg_info_p, reg_value);
- if (error.Success ())
- {
- response.Printf ("%.02x:", *reg_num_p);
- WriteRegisterValueInHexFixedWidth(response, reg_ctx_sp, *reg_info_p, &reg_value);
- response.PutChar (';');
- }
- else
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to read register '%s' index %" PRIu32 ": %s", __FUNCTION__, reg_info_p->name ? reg_info_p->name : "<unnamed-register>", *reg_num_p, error.AsCString ());
-
- }
- }
- }
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to read "
+ "register '%s' index %" PRIu32 ": %s",
+ __FUNCTION__, reg_info_p->name ? reg_info_p->name
+ : "<unnamed-register>",
+ *reg_num_p, error.AsCString());
+ }
}
+ }
}
+ }
- const char* reason_str = GetStopReasonString(tid_stop_info.reason);
- if (reason_str != nullptr)
- {
- response.Printf ("reason:%s;", reason_str);
- }
+ const char *reason_str = GetStopReasonString(tid_stop_info.reason);
+ if (reason_str != nullptr) {
+ response.Printf("reason:%s;", reason_str);
+ }
- if (!description.empty())
- {
- // Description may contains special chars, send as hex bytes.
- response.PutCString ("description:");
- response.PutCStringAsRawHex8 (description.c_str ());
- response.PutChar (';');
- }
- else if ((tid_stop_info.reason == eStopReasonException) && tid_stop_info.details.exception.type)
- {
- response.PutCString ("metype:");
- response.PutHex64 (tid_stop_info.details.exception.type);
- response.PutCString (";mecount:");
- response.PutHex32 (tid_stop_info.details.exception.data_count);
- response.PutChar (';');
-
- for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i)
- {
- response.PutCString ("medata:");
- response.PutHex64 (tid_stop_info.details.exception.data[i]);
- response.PutChar (';');
- }
+ if (!description.empty()) {
+ // Description may contains special chars, send as hex bytes.
+ response.PutCString("description:");
+ response.PutCStringAsRawHex8(description.c_str());
+ response.PutChar(';');
+ } else if ((tid_stop_info.reason == eStopReasonException) &&
+ tid_stop_info.details.exception.type) {
+ response.PutCString("metype:");
+ response.PutHex64(tid_stop_info.details.exception.type);
+ response.PutCString(";mecount:");
+ response.PutHex32(tid_stop_info.details.exception.data_count);
+ response.PutChar(';');
+
+ for (uint32_t i = 0; i < tid_stop_info.details.exception.data_count; ++i) {
+ response.PutCString("medata:");
+ response.PutHex64(tid_stop_info.details.exception.data[i]);
+ response.PutChar(';');
}
+ }
- return SendPacketNoLock (response.GetData(), response.GetSize());
+ return SendPacketNoLock(response.GetString());
}
-void
-GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited (NativeProcessProtocol *process)
-{
- assert (process && "process cannot be NULL");
-
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
-
- PacketResult result = SendStopReasonForState(StateType::eStateExited);
- if (result != PacketResult::Success)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to send stop notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID ());
- }
+void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited(
+ NativeProcessProtocol *process) {
+ assert(process && "process cannot be NULL");
- // Close the pipe to the inferior terminal i/o if we launched it
- // and set one up.
- MaybeCloseInferiorTerminalConnection ();
-
- // We are ready to exit the debug monitor.
- m_exit_now = true;
-}
-
-void
-GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped (NativeProcessProtocol *process)
-{
- assert (process && "process cannot be NULL");
-
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
-
- // Send the stop reason unless this is the stop after the
- // launch or attach.
- switch (m_inferior_prev_state)
- {
- case eStateLaunching:
- case eStateAttaching:
- // Don't send anything per debugserver behavior.
- break;
- default:
- // In all other cases, send the stop reason.
- PacketResult result = SendStopReasonForState(StateType::eStateStopped);
- if (result != PacketResult::Success)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to send stop notification for PID %" PRIu64 ", state: eStateExited", __FUNCTION__, process->GetID ());
- }
- break;
- }
-}
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
-void
-GDBRemoteCommunicationServerLLGS::ProcessStateChanged (NativeProcessProtocol *process, lldb::StateType state)
-{
- assert (process && "process cannot be NULL");
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ PacketResult result = SendStopReasonForState(StateType::eStateExited);
+ if (result != PacketResult::Success) {
if (log)
- {
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s called with NativeProcessProtocol pid %" PRIu64 ", state: %s",
- __FUNCTION__,
- process->GetID (),
- StateAsCString (state));
- }
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop "
+ "notification for PID %" PRIu64 ", state: eStateExited",
+ __FUNCTION__, process->GetID());
+ }
+
+ // Close the pipe to the inferior terminal i/o if we launched it
+ // and set one up.
+ MaybeCloseInferiorTerminalConnection();
+
+ // We are ready to exit the debug monitor.
+ m_exit_now = true;
+}
+
+void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped(
+ NativeProcessProtocol *process) {
+ assert(process && "process cannot be NULL");
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
+
+ // Send the stop reason unless this is the stop after the
+ // launch or attach.
+ switch (m_inferior_prev_state) {
+ case eStateLaunching:
+ case eStateAttaching:
+ // Don't send anything per debugserver behavior.
+ break;
+ default:
+ // In all other cases, send the stop reason.
+ PacketResult result = SendStopReasonForState(StateType::eStateStopped);
+ if (result != PacketResult::Success) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send stop "
+ "notification for PID %" PRIu64 ", state: eStateExited",
+ __FUNCTION__, process->GetID());
+ }
+ break;
+ }
+}
+
+void GDBRemoteCommunicationServerLLGS::ProcessStateChanged(
+ NativeProcessProtocol *process, lldb::StateType state) {
+ assert(process && "process cannot be NULL");
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log) {
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s called with "
+ "NativeProcessProtocol pid %" PRIu64 ", state: %s",
+ __FUNCTION__, process->GetID(), StateAsCString(state));
+ }
+
+ switch (state) {
+ case StateType::eStateRunning:
+ StartSTDIOForwarding();
+ break;
+
+ case StateType::eStateStopped:
+ // Make sure we get all of the pending stdout/stderr from the inferior
+ // and send it to the lldb host before we send the state change
+ // notification
+ SendProcessOutput();
+ // Then stop the forwarding, so that any late output (see llvm.org/pr25652)
+ // does not
+ // interfere with our protocol.
+ StopSTDIOForwarding();
+ HandleInferiorState_Stopped(process);
+ break;
- switch (state)
- {
- case StateType::eStateRunning:
- StartSTDIOForwarding();
- break;
-
- case StateType::eStateStopped:
- // Make sure we get all of the pending stdout/stderr from the inferior
- // and send it to the lldb host before we send the state change
- // notification
- SendProcessOutput();
- // Then stop the forwarding, so that any late output (see llvm.org/pr25652) does not
- // interfere with our protocol.
- StopSTDIOForwarding();
- HandleInferiorState_Stopped (process);
- break;
-
- case StateType::eStateExited:
- // Same as above
- SendProcessOutput();
- StopSTDIOForwarding();
- HandleInferiorState_Exited (process);
- break;
+ case StateType::eStateExited:
+ // Same as above
+ SendProcessOutput();
+ StopSTDIOForwarding();
+ HandleInferiorState_Exited(process);
+ break;
- default:
- if (log)
- {
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s didn't handle state change for pid %" PRIu64 ", new state: %s",
- __FUNCTION__,
- process->GetID (),
- StateAsCString (state));
- }
- break;
+ default:
+ if (log) {
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s didn't handle state "
+ "change for pid %" PRIu64 ", new state: %s",
+ __FUNCTION__, process->GetID(), StateAsCString(state));
}
+ break;
+ }
- // Remember the previous state reported to us.
- m_inferior_prev_state = state;
+ // Remember the previous state reported to us.
+ m_inferior_prev_state = state;
}
-void
-GDBRemoteCommunicationServerLLGS::DidExec (NativeProcessProtocol *process)
-{
- ClearProcessSpecificData ();
+void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) {
+ ClearProcessSpecificData();
}
-void
-GDBRemoteCommunicationServerLLGS::DataAvailableCallback ()
-{
- Log *log (GetLogIfAnyCategoriesSet(GDBR_LOG_COMM));
+void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() {
+ Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_COMM));
- if (! m_handshake_completed)
- {
- if (! HandshakeWithClient())
- {
- if(log)
- log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with client failed, exiting",
- __FUNCTION__);
- m_mainloop.RequestTermination();
- return;
- }
- m_handshake_completed = true;
+ if (!m_handshake_completed) {
+ if (!HandshakeWithClient()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s handshake with "
+ "client failed, exiting",
+ __FUNCTION__);
+ m_mainloop.RequestTermination();
+ return;
}
+ m_handshake_completed = true;
+ }
- bool interrupt = false;
- bool done = false;
- Error error;
- while (true)
- {
- const PacketResult result = GetPacketAndSendResponse (0, error, interrupt, done);
- if (result == PacketResult::ErrorReplyTimeout)
- break; // No more packets in the queue
-
- if ((result != PacketResult::Success))
- {
- if(log)
- log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet failed: %s",
- __FUNCTION__, error.AsCString());
- m_mainloop.RequestTermination();
- break;
- }
+ bool interrupt = false;
+ bool done = false;
+ Error error;
+ while (true) {
+ const PacketResult result = GetPacketAndSendResponse(
+ std::chrono::microseconds(0), error, interrupt, done);
+ if (result == PacketResult::ErrorReplyTimeout)
+ break; // No more packets in the queue
+
+ if ((result != PacketResult::Success)) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s processing a packet "
+ "failed: %s",
+ __FUNCTION__, error.AsCString());
+ m_mainloop.RequestTermination();
+ break;
}
+ }
}
-Error
-GDBRemoteCommunicationServerLLGS::InitializeConnection (std::unique_ptr<Connection> &&connection)
-{
- IOObjectSP read_object_sp = connection->GetReadObject();
- GDBRemoteCommunicationServer::SetConnection(connection.release());
+Error GDBRemoteCommunicationServerLLGS::InitializeConnection(
+ std::unique_ptr<Connection> &&connection) {
+ IOObjectSP read_object_sp = connection->GetReadObject();
+ GDBRemoteCommunicationServer::SetConnection(connection.release());
- Error error;
- m_network_handle_up = m_mainloop.RegisterReadObject(read_object_sp,
- [this] (MainLoopBase &) { DataAvailableCallback(); }, error);
- return error;
+ Error error;
+ m_network_handle_up = m_mainloop.RegisterReadObject(
+ read_object_sp, [this](MainLoopBase &) { DataAvailableCallback(); },
+ error);
+ return error;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::SendONotification (const char *buffer, uint32_t len)
-{
- if ((buffer == nullptr) || (len == 0))
- {
- // Nothing to send.
- return PacketResult::Success;
- }
-
- StreamString response;
- response.PutChar ('O');
- response.PutBytesAsRawHex8 (buffer, len);
-
- return SendPacketNoLock (response.GetData (), response.GetSize ());
-}
-
-Error
-GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor (int fd)
-{
- Error error;
-
- // Set up the reading/handling of process I/O
- std::unique_ptr<ConnectionFileDescriptor> conn_up (new ConnectionFileDescriptor (fd, true));
- if (!conn_up)
- {
- error.SetErrorString ("failed to create ConnectionFileDescriptor");
- return error;
- }
+GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer,
+ uint32_t len) {
+ if ((buffer == nullptr) || (len == 0)) {
+ // Nothing to send.
+ return PacketResult::Success;
+ }
- m_stdio_communication.SetCloseOnEOF (false);
- m_stdio_communication.SetConnection (conn_up.release());
- if (!m_stdio_communication.IsConnected ())
- {
- error.SetErrorString ("failed to set connection for inferior I/O communication");
- return error;
- }
+ StreamString response;
+ response.PutChar('O');
+ response.PutBytesAsRawHex8(buffer, len);
- return Error();
+ return SendPacketNoLock(response.GetString());
}
-void
-GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding()
-{
- // Don't forward if not connected (e.g. when attaching).
- if (! m_stdio_communication.IsConnected())
- return;
-
- // llgs local-process debugging may specify PTY paths, which will make these
- // file actions non-null
- // process launch -e/o will also make these file actions non-null
- // nullptr means that the traffic is expected to flow over gdb-remote protocol
- if ( m_process_launch_info.GetFileActionForFD(STDOUT_FILENO) &&
- m_process_launch_info.GetFileActionForFD(STDERR_FILENO))
- return;
-
- Error error;
- lldbassert(! m_stdio_handle_up);
- m_stdio_handle_up = m_mainloop.RegisterReadObject(
- m_stdio_communication.GetConnection()->GetReadObject(),
- [this] (MainLoopBase &) { SendProcessOutput(); }, error);
-
- if (! m_stdio_handle_up)
- {
- // Not much we can do about the failure. Log it and continue without forwarding.
- if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
- log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio forwarding: %s",
- __FUNCTION__, error.AsCString());
- }
-}
+Error GDBRemoteCommunicationServerLLGS::SetSTDIOFileDescriptor(int fd) {
+ Error error;
-void
-GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding()
-{
- m_stdio_handle_up.reset();
-}
+ // Set up the reading/handling of process I/O
+ std::unique_ptr<ConnectionFileDescriptor> conn_up(
+ new ConnectionFileDescriptor(fd, true));
+ if (!conn_up) {
+ error.SetErrorString("failed to create ConnectionFileDescriptor");
+ return error;
+ }
-void
-GDBRemoteCommunicationServerLLGS::SendProcessOutput()
-{
- char buffer[1024];
- ConnectionStatus status;
- Error error;
- while (true)
- {
- size_t bytes_read = m_stdio_communication.Read(buffer, sizeof buffer, 0, status, &error);
- switch (status)
- {
- case eConnectionStatusSuccess:
- SendONotification(buffer, bytes_read);
- break;
- case eConnectionStatusLostConnection:
- case eConnectionStatusEndOfFile:
- case eConnectionStatusError:
- case eConnectionStatusNoConnection:
- if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
- log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio forwarding as communication returned status %d (error: %s)", __FUNCTION__, status, error.AsCString());
- m_stdio_handle_up.reset();
- return;
-
- case eConnectionStatusInterrupted:
- case eConnectionStatusTimedOut:
- return;
- }
- }
+ m_stdio_communication.SetCloseOnEOF(false);
+ m_stdio_communication.SetConnection(conn_up.release());
+ if (!m_stdio_communication.IsConnected()) {
+ error.SetErrorString(
+ "failed to set connection for inferior I/O communication");
+ return error;
+ }
+
+ return Error();
+}
+
+void GDBRemoteCommunicationServerLLGS::StartSTDIOForwarding() {
+ // Don't forward if not connected (e.g. when attaching).
+ if (!m_stdio_communication.IsConnected())
+ return;
+
+ Error error;
+ lldbassert(!m_stdio_handle_up);
+ m_stdio_handle_up = m_mainloop.RegisterReadObject(
+ m_stdio_communication.GetConnection()->GetReadObject(),
+ [this](MainLoopBase &) { SendProcessOutput(); }, error);
+
+ if (!m_stdio_handle_up) {
+ // Not much we can do about the failure. Log it and continue without
+ // forwarding.
+ if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to set up stdio "
+ "forwarding: %s",
+ __FUNCTION__, error.AsCString());
+ }
+}
+
+void GDBRemoteCommunicationServerLLGS::StopSTDIOForwarding() {
+ m_stdio_handle_up.reset();
+}
+
+void GDBRemoteCommunicationServerLLGS::SendProcessOutput() {
+ char buffer[1024];
+ ConnectionStatus status;
+ Error error;
+ while (true) {
+ size_t bytes_read = m_stdio_communication.Read(
+ buffer, sizeof buffer, std::chrono::microseconds(0), status, &error);
+ switch (status) {
+ case eConnectionStatusSuccess:
+ SendONotification(buffer, bytes_read);
+ break;
+ case eConnectionStatusLostConnection:
+ case eConnectionStatusEndOfFile:
+ case eConnectionStatusError:
+ case eConnectionStatusNoConnection:
+ if (Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS))
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s Stopping stdio "
+ "forwarding as communication returned status %d (error: "
+ "%s)",
+ __FUNCTION__, status, error.AsCString());
+ m_stdio_handle_up.reset();
+ return;
+
+ case eConnectionStatusInterrupted:
+ case eConnectionStatusTimedOut:
+ return;
+ }
+ }
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
-{
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse (68);
+GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
+ StringExtractorGDBRemote &packet) {
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(68);
- lldb::pid_t pid = m_debugged_process_sp->GetID ();
+ lldb::pid_t pid = m_debugged_process_sp->GetID();
- if (pid == LLDB_INVALID_PROCESS_ID)
- return SendErrorResponse (1);
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(1);
- ProcessInstanceInfo proc_info;
- if (!Host::GetProcessInfo (pid, proc_info))
- return SendErrorResponse (1);
+ ProcessInstanceInfo proc_info;
+ if (!Host::GetProcessInfo(pid, proc_info))
+ return SendErrorResponse(1);
- StreamString response;
- CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
- return SendPacketNoLock (response.GetData (), response.GetSize ());
+ StreamString response;
+ CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qC (StringExtractorGDBRemote &packet)
-{
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse (68);
+GDBRemoteCommunicationServerLLGS::Handle_qC(StringExtractorGDBRemote &packet) {
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(68);
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
- lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID ();
- SetCurrentThreadID (tid);
+ // Make sure we set the current thread so g and p packets return
+ // the data the gdb will expect.
+ lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID();
+ SetCurrentThreadID(tid);
- NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetCurrentThread ();
- if (!thread_sp)
- return SendErrorResponse (69);
+ NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetCurrentThread();
+ if (!thread_sp)
+ return SendErrorResponse(69);
- StreamString response;
- response.Printf ("QC%" PRIx64, thread_sp->GetID ());
+ StreamString response;
+ response.Printf("QC%" PRIx64, thread_sp->GetID());
- return SendPacketNoLock (response.GetData(), response.GetSize());
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_k (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- StopSTDIOForwarding();
+ StopSTDIOForwarding();
- if (! m_debugged_process_sp)
- {
- if (log)
- log->Printf("GDBRemoteCommunicationServerLLGS::%s No debugged process found.", __FUNCTION__);
- return PacketResult::Success;
- }
+ if (!m_debugged_process_sp) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s No debugged process found.",
+ __FUNCTION__);
+ return PacketResult::Success;
+ }
- Error error = m_debugged_process_sp->Kill();
- if (error.Fail() && log)
- log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged process %" PRIu64 ": %s",
- __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString());
+ Error error = m_debugged_process_sp->Kill();
+ if (error.Fail() && log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s Failed to kill debugged "
+ "process %" PRIu64 ": %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
- // No OK response for kill packet.
- // return SendOKResponse ();
- return PacketResult::Success;
+ // No OK response for kill packet.
+ // return SendOKResponse ();
+ return PacketResult::Success;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("QSetDisableASLR:"));
- if (packet.GetU32(0))
- m_process_launch_info.GetFlags().Set (eLaunchFlagDisableASLR);
- else
- m_process_launch_info.GetFlags().Clear (eLaunchFlagDisableASLR);
- return SendOKResponse ();
+GDBRemoteCommunicationServerLLGS::Handle_QSetDisableASLR(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("QSetDisableASLR:"));
+ if (packet.GetU32(0))
+ m_process_launch_info.GetFlags().Set(eLaunchFlagDisableASLR);
+ else
+ m_process_launch_info.GetFlags().Clear(eLaunchFlagDisableASLR);
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos (::strlen ("QSetWorkingDir:"));
- std::string path;
- packet.GetHexByteString (path);
- m_process_launch_info.SetWorkingDirectory(FileSpec{path, true});
- return SendOKResponse ();
+GDBRemoteCommunicationServerLLGS::Handle_QSetWorkingDir(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("QSetWorkingDir:"));
+ std::string path;
+ packet.GetHexByteString(path);
+ m_process_launch_info.SetWorkingDirectory(FileSpec{path, true});
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
-{
- FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()};
- if (working_dir)
- {
- StreamString response;
- response.PutCStringAsRawHex8(working_dir.GetCString());
- return SendPacketNoLock(response.GetData(), response.GetSize());
- }
+GDBRemoteCommunicationServerLLGS::Handle_qGetWorkingDir(
+ StringExtractorGDBRemote &packet) {
+ FileSpec working_dir{m_process_launch_info.GetWorkingDirectory()};
+ if (working_dir) {
+ StreamString response;
+ response.PutCStringAsRawHex8(working_dir.GetCString());
+ return SendPacketNoLock(response.GetString());
+ }
- return SendErrorResponse(14);
+ return SendErrorResponse(14);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_C (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_THREAD));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
-
- // Ensure we have a native process.
- if (!m_debugged_process_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s no debugged process shared pointer", __FUNCTION__);
- return SendErrorResponse (0x36);
- }
-
- // Pull out the signal number.
- packet.SetFilePos (::strlen ("C"));
- if (packet.GetBytesLeft () < 1)
- {
- // Shouldn't be using a C without a signal.
- return SendIllFormedResponse (packet, "C packet specified without signal.");
- }
- const uint32_t signo = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
- if (signo == std::numeric_limits<uint32_t>::max ())
- return SendIllFormedResponse (packet, "failed to parse signal number");
-
- // Handle optional continue address.
- if (packet.GetBytesLeft () > 0)
- {
- // FIXME add continue at address support for $C{signo}[;{continue-address}].
- if (*packet.Peek () == ';')
- return SendUnimplementedResponse (packet.GetStringRef().c_str());
- else
- return SendIllFormedResponse (packet, "unexpected content after $C{signal-number}");
- }
+GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
- ResumeActionList resume_actions (StateType::eStateRunning, 0);
- Error error;
-
- // We have two branches: what to do if a continue thread is specified (in which case we target
- // sending the signal to that thread), or when we don't have a continue thread set (in which
- // case we send a signal to the process).
-
- // TODO discuss with Greg Clayton, make sure this makes sense.
-
- lldb::tid_t signal_tid = GetContinueThreadID ();
- if (signal_tid != LLDB_INVALID_THREAD_ID)
- {
- // The resume action for the continue thread (or all threads if a continue thread is not set).
- ResumeAction action = { GetContinueThreadID (), StateType::eStateRunning, static_cast<int> (signo) };
-
- // Add the action for the continue thread (or all threads when the continue thread isn't present).
- resume_actions.Append (action);
- }
+ // Ensure we have a native process.
+ if (!m_debugged_process_sp) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process "
+ "shared pointer",
+ __FUNCTION__);
+ return SendErrorResponse(0x36);
+ }
+
+ // Pull out the signal number.
+ packet.SetFilePos(::strlen("C"));
+ if (packet.GetBytesLeft() < 1) {
+ // Shouldn't be using a C without a signal.
+ return SendIllFormedResponse(packet, "C packet specified without signal.");
+ }
+ const uint32_t signo =
+ packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
+ if (signo == std::numeric_limits<uint32_t>::max())
+ return SendIllFormedResponse(packet, "failed to parse signal number");
+
+ // Handle optional continue address.
+ if (packet.GetBytesLeft() > 0) {
+ // FIXME add continue at address support for $C{signo}[;{continue-address}].
+ if (*packet.Peek() == ';')
+ return SendUnimplementedResponse(packet.GetStringRef().c_str());
else
- {
- // Send the signal to the process since we weren't targeting a specific continue thread with the signal.
- error = m_debugged_process_sp->Signal (signo);
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to send signal for process %" PRIu64 ": %s",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- error.AsCString ());
-
- return SendErrorResponse (0x52);
- }
- }
-
- // Resume the threads.
- error = m_debugged_process_sp->Resume (resume_actions);
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to resume threads for process %" PRIu64 ": %s",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- error.AsCString ());
+ return SendIllFormedResponse(
+ packet, "unexpected content after $C{signal-number}");
+ }
+
+ ResumeActionList resume_actions(StateType::eStateRunning, 0);
+ Error error;
+
+ // We have two branches: what to do if a continue thread is specified (in
+ // which case we target
+ // sending the signal to that thread), or when we don't have a continue thread
+ // set (in which
+ // case we send a signal to the process).
+
+ // TODO discuss with Greg Clayton, make sure this makes sense.
+
+ lldb::tid_t signal_tid = GetContinueThreadID();
+ if (signal_tid != LLDB_INVALID_THREAD_ID) {
+ // The resume action for the continue thread (or all threads if a continue
+ // thread is not set).
+ ResumeAction action = {GetContinueThreadID(), StateType::eStateRunning,
+ static_cast<int>(signo)};
+
+ // Add the action for the continue thread (or all threads when the continue
+ // thread isn't present).
+ resume_actions.Append(action);
+ } else {
+ // Send the signal to the process since we weren't targeting a specific
+ // continue thread with the signal.
+ error = m_debugged_process_sp->Signal(signo);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to send "
+ "signal for process %" PRIu64 ": %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
+
+ return SendErrorResponse(0x52);
+ }
+ }
+
+ // Resume the threads.
+ error = m_debugged_process_sp->Resume(resume_actions);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to resume "
+ "threads for process %" PRIu64 ": %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
- return SendErrorResponse (0x38);
- }
+ return SendErrorResponse(0x38);
+ }
- // Don't send an "OK" packet; response is the stopped/exited message.
- return PacketResult::Success;
+ // Don't send an "OK" packet; response is the stopped/exited message.
+ return PacketResult::Success;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_c (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_THREAD));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
-
- packet.SetFilePos (packet.GetFilePos() + ::strlen ("c"));
+GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__);
- // For now just support all continue.
- const bool has_continue_address = (packet.GetBytesLeft () > 0);
- if (has_continue_address)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s not implemented for c{address} variant [%s remains]", __FUNCTION__, packet.Peek ());
- return SendUnimplementedResponse (packet.GetStringRef().c_str());
- }
+ packet.SetFilePos(packet.GetFilePos() + ::strlen("c"));
- // Ensure we have a native process.
- if (!m_debugged_process_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s no debugged process shared pointer", __FUNCTION__);
- return SendErrorResponse (0x36);
- }
+ // For now just support all continue.
+ const bool has_continue_address = (packet.GetBytesLeft() > 0);
+ if (has_continue_address) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s not implemented for "
+ "c{address} variant [%s remains]",
+ __FUNCTION__, packet.Peek());
+ return SendUnimplementedResponse(packet.GetStringRef().c_str());
+ }
+
+ // Ensure we have a native process.
+ if (!m_debugged_process_sp) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process "
+ "shared pointer",
+ __FUNCTION__);
+ return SendErrorResponse(0x36);
+ }
- // Build the ResumeActionList
- ResumeActionList actions (StateType::eStateRunning, 0);
+ // Build the ResumeActionList
+ ResumeActionList actions(StateType::eStateRunning, 0);
- Error error = m_debugged_process_sp->Resume (actions);
- if (error.Fail ())
- {
- if (log)
- {
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s c failed for process %" PRIu64 ": %s",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- error.AsCString ());
- }
- return SendErrorResponse (GDBRemoteServerError::eErrorResume);
+ Error error = m_debugged_process_sp->Resume(actions);
+ if (error.Fail()) {
+ if (log) {
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s c failed for process %" PRIu64
+ ": %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString());
}
+ return SendErrorResponse(GDBRemoteServerError::eErrorResume);
+ }
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID ());
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
- // No response required from continue.
- return PacketResult::Success;
+ // No response required from continue.
+ return PacketResult::Success;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_vCont_actions (StringExtractorGDBRemote &packet)
-{
- StreamString response;
- response.Printf("vCont;c;C;s;S");
+GDBRemoteCommunicationServerLLGS::Handle_vCont_actions(
+ StringExtractorGDBRemote &packet) {
+ StreamString response;
+ response.Printf("vCont;c;C;s;S");
- return SendPacketNoLock(response.GetData(), response.GetSize());
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_vCont (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s handling vCont packet", __FUNCTION__);
-
- packet.SetFilePos (::strlen ("vCont"));
+GDBRemoteCommunicationServerLLGS::Handle_vCont(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s handling vCont packet",
+ __FUNCTION__);
- if (packet.GetBytesLeft() == 0)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s missing action from vCont package", __FUNCTION__);
- return SendIllFormedResponse (packet, "Missing action from vCont package");
- }
+ packet.SetFilePos(::strlen("vCont"));
- // Check if this is all continue (no options or ";c").
- if (::strcmp (packet.Peek (), ";c") == 0)
- {
- // Move past the ';', then do a simple 'c'.
- packet.SetFilePos (packet.GetFilePos () + 1);
- return Handle_c (packet);
- }
- else if (::strcmp (packet.Peek (), ";s") == 0)
- {
- // Move past the ';', then do a simple 's'.
- packet.SetFilePos (packet.GetFilePos () + 1);
- return Handle_s (packet);
- }
+ if (packet.GetBytesLeft() == 0) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s missing action from "
+ "vCont package",
+ __FUNCTION__);
+ return SendIllFormedResponse(packet, "Missing action from vCont package");
+ }
+
+ // Check if this is all continue (no options or ";c").
+ if (::strcmp(packet.Peek(), ";c") == 0) {
+ // Move past the ';', then do a simple 'c'.
+ packet.SetFilePos(packet.GetFilePos() + 1);
+ return Handle_c(packet);
+ } else if (::strcmp(packet.Peek(), ";s") == 0) {
+ // Move past the ';', then do a simple 's'.
+ packet.SetFilePos(packet.GetFilePos() + 1);
+ return Handle_s(packet);
+ }
+
+ // Ensure we have a native process.
+ if (!m_debugged_process_sp) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s no debugged process "
+ "shared pointer",
+ __FUNCTION__);
+ return SendErrorResponse(0x36);
+ }
+
+ ResumeActionList thread_actions;
+
+ while (packet.GetBytesLeft() && *packet.Peek() == ';') {
+ // Skip the semi-colon.
+ packet.GetChar();
+
+ // Build up the thread action.
+ ResumeAction thread_action;
+ thread_action.tid = LLDB_INVALID_THREAD_ID;
+ thread_action.state = eStateInvalid;
+ thread_action.signal = 0;
+
+ const char action = packet.GetChar();
+ switch (action) {
+ case 'C':
+ thread_action.signal = packet.GetHexMaxU32(false, 0);
+ if (thread_action.signal == 0)
+ return SendIllFormedResponse(
+ packet, "Could not parse signal in vCont packet C action");
+ LLVM_FALLTHROUGH;
+
+ case 'c':
+ // Continue
+ thread_action.state = eStateRunning;
+ break;
+
+ case 'S':
+ thread_action.signal = packet.GetHexMaxU32(false, 0);
+ if (thread_action.signal == 0)
+ return SendIllFormedResponse(
+ packet, "Could not parse signal in vCont packet S action");
+ LLVM_FALLTHROUGH;
+
+ case 's':
+ // Step
+ thread_action.state = eStateStepping;
+ break;
- // Ensure we have a native process.
- if (!m_debugged_process_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s no debugged process shared pointer", __FUNCTION__);
- return SendErrorResponse (0x36);
+ default:
+ return SendIllFormedResponse(packet, "Unsupported vCont action");
+ break;
}
- ResumeActionList thread_actions;
-
- while (packet.GetBytesLeft () && *packet.Peek () == ';')
- {
- // Skip the semi-colon.
- packet.GetChar ();
-
- // Build up the thread action.
- ResumeAction thread_action;
- thread_action.tid = LLDB_INVALID_THREAD_ID;
- thread_action.state = eStateInvalid;
- thread_action.signal = 0;
-
- const char action = packet.GetChar ();
- switch (action)
- {
- case 'C':
- thread_action.signal = packet.GetHexMaxU32 (false, 0);
- if (thread_action.signal == 0)
- return SendIllFormedResponse (packet, "Could not parse signal in vCont packet C action");
- LLVM_FALLTHROUGH;
-
- case 'c':
- // Continue
- thread_action.state = eStateRunning;
- break;
-
- case 'S':
- thread_action.signal = packet.GetHexMaxU32 (false, 0);
- if (thread_action.signal == 0)
- return SendIllFormedResponse (packet, "Could not parse signal in vCont packet S action");
- LLVM_FALLTHROUGH;
-
- case 's':
- // Step
- thread_action.state = eStateStepping;
- break;
-
- default:
- return SendIllFormedResponse (packet, "Unsupported vCont action");
- break;
- }
-
- // Parse out optional :{thread-id} value.
- if (packet.GetBytesLeft () && (*packet.Peek () == ':'))
- {
- // Consume the separator.
- packet.GetChar ();
-
- thread_action.tid = packet.GetHexMaxU32 (false, LLDB_INVALID_THREAD_ID);
- if (thread_action.tid == LLDB_INVALID_THREAD_ID)
- return SendIllFormedResponse (packet, "Could not parse thread number in vCont packet");
- }
+ // Parse out optional :{thread-id} value.
+ if (packet.GetBytesLeft() && (*packet.Peek() == ':')) {
+ // Consume the separator.
+ packet.GetChar();
- thread_actions.Append (thread_action);
+ thread_action.tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
+ if (thread_action.tid == LLDB_INVALID_THREAD_ID)
+ return SendIllFormedResponse(
+ packet, "Could not parse thread number in vCont packet");
}
- Error error = m_debugged_process_sp->Resume (thread_actions);
- if (error.Fail ())
- {
- if (log)
- {
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s vCont failed for process %" PRIu64 ": %s",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- error.AsCString ());
- }
- return SendErrorResponse (GDBRemoteServerError::eErrorResume);
+ thread_actions.Append(thread_action);
+ }
+
+ Error error = m_debugged_process_sp->Resume(thread_actions);
+ if (error.Fail()) {
+ if (log) {
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s vCont failed for "
+ "process %" PRIu64 ": %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
}
+ return SendErrorResponse(GDBRemoteServerError::eErrorResume);
+ }
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID ());
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s continued process %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
- // No response required from vCont.
- return PacketResult::Success;
+ // No response required from vCont.
+ return PacketResult::Success;
}
-void
-GDBRemoteCommunicationServerLLGS::SetCurrentThreadID (lldb::tid_t tid)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s setting current thread id to %" PRIu64, __FUNCTION__, tid);
+void GDBRemoteCommunicationServerLLGS::SetCurrentThreadID(lldb::tid_t tid) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s setting current thread "
+ "id to %" PRIu64,
+ __FUNCTION__, tid);
- m_current_tid = tid;
- if (m_debugged_process_sp)
- m_debugged_process_sp->SetCurrentThreadID (m_current_tid);
+ m_current_tid = tid;
+ if (m_debugged_process_sp)
+ m_debugged_process_sp->SetCurrentThreadID(m_current_tid);
}
-void
-GDBRemoteCommunicationServerLLGS::SetContinueThreadID (lldb::tid_t tid)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_THREAD));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s setting continue thread id to %" PRIu64, __FUNCTION__, tid);
+void GDBRemoteCommunicationServerLLGS::SetContinueThreadID(lldb::tid_t tid) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s setting continue thread "
+ "id to %" PRIu64,
+ __FUNCTION__, tid);
- m_continue_tid = tid;
+ m_continue_tid = tid;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_stop_reason (StringExtractorGDBRemote &packet)
-{
- // Handle the $? gdbremote command.
+GDBRemoteCommunicationServerLLGS::Handle_stop_reason(
+ StringExtractorGDBRemote &packet) {
+ // Handle the $? gdbremote command.
- // If no process, indicate error
- if (!m_debugged_process_sp)
- return SendErrorResponse (02);
+ // If no process, indicate error
+ if (!m_debugged_process_sp)
+ return SendErrorResponse(02);
- return SendStopReasonForState (m_debugged_process_sp->GetState());
+ return SendStopReasonForState(m_debugged_process_sp->GetState());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::SendStopReasonForState (lldb::StateType process_state)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- switch (process_state)
- {
- case eStateAttaching:
- case eStateLaunching:
- case eStateRunning:
- case eStateStepping:
- case eStateDetached:
- // NOTE: gdb protocol doc looks like it should return $OK
- // when everything is running (i.e. no stopped result).
- return PacketResult::Success; // Ignore
-
- case eStateSuspended:
- case eStateStopped:
- case eStateCrashed:
- {
- lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID ();
- // Make sure we set the current thread so g and p packets return
- // the data the gdb will expect.
- SetCurrentThreadID (tid);
- return SendStopReplyPacketForThread (tid);
- }
+GDBRemoteCommunicationServerLLGS::SendStopReasonForState(
+ lldb::StateType process_state) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ switch (process_state) {
+ case eStateAttaching:
+ case eStateLaunching:
+ case eStateRunning:
+ case eStateStepping:
+ case eStateDetached:
+ // NOTE: gdb protocol doc looks like it should return $OK
+ // when everything is running (i.e. no stopped result).
+ return PacketResult::Success; // Ignore
+
+ case eStateSuspended:
+ case eStateStopped:
+ case eStateCrashed: {
+ lldb::tid_t tid = m_debugged_process_sp->GetCurrentThreadID();
+ // Make sure we set the current thread so g and p packets return
+ // the data the gdb will expect.
+ SetCurrentThreadID(tid);
+ return SendStopReplyPacketForThread(tid);
+ }
- case eStateInvalid:
- case eStateUnloaded:
- case eStateExited:
- return SendWResponse(m_debugged_process_sp.get());
+ case eStateInvalid:
+ case eStateUnloaded:
+ case eStateExited:
+ return SendWResponse(m_debugged_process_sp.get());
- default:
- if (log)
- {
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 ", current state reporting not handled: %s",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- StateAsCString (process_state));
- }
- break;
+ default:
+ if (log) {
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ ", current state reporting not handled: %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ StateAsCString(process_state));
}
-
- return SendErrorResponse (0);
+ break;
+ }
+
+ return SendErrorResponse(0);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo (StringExtractorGDBRemote &packet)
-{
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse (68);
-
- // Ensure we have a thread.
- NativeThreadProtocolSP thread_sp (m_debugged_process_sp->GetThreadAtIndex (0));
- if (!thread_sp)
- return SendErrorResponse (69);
-
- // Get the register context for the first thread.
- NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
- if (!reg_context_sp)
- return SendErrorResponse (69);
-
- // Parse out the register number from the request.
- packet.SetFilePos (strlen("qRegisterInfo"));
- const uint32_t reg_index = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
- if (reg_index == std::numeric_limits<uint32_t>::max ())
- return SendErrorResponse (69);
-
- // Return the end of registers response if we've iterated one past the end of the register set.
- if (reg_index >= reg_context_sp->GetUserRegisterCount ())
- return SendErrorResponse (69);
-
- const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index);
- if (!reg_info)
- return SendErrorResponse (69);
-
- // Build the reginfos response.
- StreamGDBRemote response;
-
- response.PutCString ("name:");
- response.PutCString (reg_info->name);
- response.PutChar (';');
-
- if (reg_info->alt_name && reg_info->alt_name[0])
- {
- response.PutCString ("alt-name:");
- response.PutCString (reg_info->alt_name);
- response.PutChar (';');
- }
-
- response.Printf ("bitsize:%" PRIu32 ";offset:%" PRIu32 ";", reg_info->byte_size * 8, reg_info->byte_offset);
-
- switch (reg_info->encoding)
- {
- case eEncodingUint: response.PutCString ("encoding:uint;"); break;
- case eEncodingSint: response.PutCString ("encoding:sint;"); break;
- case eEncodingIEEE754: response.PutCString ("encoding:ieee754;"); break;
- case eEncodingVector: response.PutCString ("encoding:vector;"); break;
- default: break;
- }
-
- switch (reg_info->format)
- {
- case eFormatBinary: response.PutCString ("format:binary;"); break;
- case eFormatDecimal: response.PutCString ("format:decimal;"); break;
- case eFormatHex: response.PutCString ("format:hex;"); break;
- case eFormatFloat: response.PutCString ("format:float;"); break;
- case eFormatVectorOfSInt8: response.PutCString ("format:vector-sint8;"); break;
- case eFormatVectorOfUInt8: response.PutCString ("format:vector-uint8;"); break;
- case eFormatVectorOfSInt16: response.PutCString ("format:vector-sint16;"); break;
- case eFormatVectorOfUInt16: response.PutCString ("format:vector-uint16;"); break;
- case eFormatVectorOfSInt32: response.PutCString ("format:vector-sint32;"); break;
- case eFormatVectorOfUInt32: response.PutCString ("format:vector-uint32;"); break;
- case eFormatVectorOfFloat32: response.PutCString ("format:vector-float32;"); break;
- case eFormatVectorOfUInt128: response.PutCString ("format:vector-uint128;"); break;
- default: break;
- };
-
- const char *const register_set_name = reg_context_sp->GetRegisterSetNameForRegisterAtIndex(reg_index);
- if (register_set_name)
- {
- response.PutCString ("set:");
- response.PutCString (register_set_name);
- response.PutChar (';');
- }
-
- if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
- response.Printf ("ehframe:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
-
- if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
- response.Printf ("dwarf:%" PRIu32 ";", reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
-
- switch (reg_info->kinds[RegisterKind::eRegisterKindGeneric])
- {
- case LLDB_REGNUM_GENERIC_PC: response.PutCString("generic:pc;"); break;
- case LLDB_REGNUM_GENERIC_SP: response.PutCString("generic:sp;"); break;
- case LLDB_REGNUM_GENERIC_FP: response.PutCString("generic:fp;"); break;
- case LLDB_REGNUM_GENERIC_RA: response.PutCString("generic:ra;"); break;
- case LLDB_REGNUM_GENERIC_FLAGS: response.PutCString("generic:flags;"); break;
- case LLDB_REGNUM_GENERIC_ARG1: response.PutCString("generic:arg1;"); break;
- case LLDB_REGNUM_GENERIC_ARG2: response.PutCString("generic:arg2;"); break;
- case LLDB_REGNUM_GENERIC_ARG3: response.PutCString("generic:arg3;"); break;
- case LLDB_REGNUM_GENERIC_ARG4: response.PutCString("generic:arg4;"); break;
- case LLDB_REGNUM_GENERIC_ARG5: response.PutCString("generic:arg5;"); break;
- case LLDB_REGNUM_GENERIC_ARG6: response.PutCString("generic:arg6;"); break;
- case LLDB_REGNUM_GENERIC_ARG7: response.PutCString("generic:arg7;"); break;
- case LLDB_REGNUM_GENERIC_ARG8: response.PutCString("generic:arg8;"); break;
- default: break;
- }
-
- if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM)
- {
- response.PutCString ("container-regs:");
- int i = 0;
- for (const uint32_t *reg_num = reg_info->value_regs; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i)
- {
- if (i > 0)
- response.PutChar (',');
- response.Printf ("%" PRIx32, *reg_num);
- }
- response.PutChar (';');
- }
-
- if (reg_info->invalidate_regs && reg_info->invalidate_regs[0])
- {
- response.PutCString ("invalidate-regs:");
- int i = 0;
- for (const uint32_t *reg_num = reg_info->invalidate_regs; *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i)
- {
- if (i > 0)
- response.PutChar (',');
- response.Printf ("%" PRIx32, *reg_num);
- }
- response.PutChar (';');
- }
-
- if (reg_info->dynamic_size_dwarf_expr_bytes)
- {
- const size_t dwarf_opcode_len = reg_info->dynamic_size_dwarf_len;
- response.PutCString("dynamic_size_dwarf_expr_bytes:");
- for(uint32_t i = 0; i < dwarf_opcode_len; ++i)
- response.PutHex8 (reg_info->dynamic_size_dwarf_expr_bytes[i]);
- response.PutChar(';');
- }
- return SendPacketNoLock(response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo(
+ StringExtractorGDBRemote &packet) {
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(68);
+
+ // Ensure we have a thread.
+ NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadAtIndex(0));
+ if (!thread_sp)
+ return SendErrorResponse(69);
+
+ // Get the register context for the first thread.
+ NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext());
+ if (!reg_context_sp)
+ return SendErrorResponse(69);
+
+ // Parse out the register number from the request.
+ packet.SetFilePos(strlen("qRegisterInfo"));
+ const uint32_t reg_index =
+ packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
+ if (reg_index == std::numeric_limits<uint32_t>::max())
+ return SendErrorResponse(69);
+
+ // Return the end of registers response if we've iterated one past the end of
+ // the register set.
+ if (reg_index >= reg_context_sp->GetUserRegisterCount())
+ return SendErrorResponse(69);
+
+ const RegisterInfo *reg_info =
+ reg_context_sp->GetRegisterInfoAtIndex(reg_index);
+ if (!reg_info)
+ return SendErrorResponse(69);
+
+ // Build the reginfos response.
+ StreamGDBRemote response;
+
+ response.PutCString("name:");
+ response.PutCString(reg_info->name);
+ response.PutChar(';');
+
+ if (reg_info->alt_name && reg_info->alt_name[0]) {
+ response.PutCString("alt-name:");
+ response.PutCString(reg_info->alt_name);
+ response.PutChar(';');
+ }
+
+ response.Printf("bitsize:%" PRIu32 ";offset:%" PRIu32 ";",
+ reg_info->byte_size * 8, reg_info->byte_offset);
+
+ switch (reg_info->encoding) {
+ case eEncodingUint:
+ response.PutCString("encoding:uint;");
+ break;
+ case eEncodingSint:
+ response.PutCString("encoding:sint;");
+ break;
+ case eEncodingIEEE754:
+ response.PutCString("encoding:ieee754;");
+ break;
+ case eEncodingVector:
+ response.PutCString("encoding:vector;");
+ break;
+ default:
+ break;
+ }
+
+ switch (reg_info->format) {
+ case eFormatBinary:
+ response.PutCString("format:binary;");
+ break;
+ case eFormatDecimal:
+ response.PutCString("format:decimal;");
+ break;
+ case eFormatHex:
+ response.PutCString("format:hex;");
+ break;
+ case eFormatFloat:
+ response.PutCString("format:float;");
+ break;
+ case eFormatVectorOfSInt8:
+ response.PutCString("format:vector-sint8;");
+ break;
+ case eFormatVectorOfUInt8:
+ response.PutCString("format:vector-uint8;");
+ break;
+ case eFormatVectorOfSInt16:
+ response.PutCString("format:vector-sint16;");
+ break;
+ case eFormatVectorOfUInt16:
+ response.PutCString("format:vector-uint16;");
+ break;
+ case eFormatVectorOfSInt32:
+ response.PutCString("format:vector-sint32;");
+ break;
+ case eFormatVectorOfUInt32:
+ response.PutCString("format:vector-uint32;");
+ break;
+ case eFormatVectorOfFloat32:
+ response.PutCString("format:vector-float32;");
+ break;
+ case eFormatVectorOfUInt64:
+ response.PutCString("format:vector-uint64;");
+ break;
+ case eFormatVectorOfUInt128:
+ response.PutCString("format:vector-uint128;");
+ break;
+ default:
+ break;
+ };
+
+ const char *const register_set_name =
+ reg_context_sp->GetRegisterSetNameForRegisterAtIndex(reg_index);
+ if (register_set_name) {
+ response.PutCString("set:");
+ response.PutCString(register_set_name);
+ response.PutChar(';');
+ }
+
+ if (reg_info->kinds[RegisterKind::eRegisterKindEHFrame] !=
+ LLDB_INVALID_REGNUM)
+ response.Printf("ehframe:%" PRIu32 ";",
+ reg_info->kinds[RegisterKind::eRegisterKindEHFrame]);
+
+ if (reg_info->kinds[RegisterKind::eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
+ response.Printf("dwarf:%" PRIu32 ";",
+ reg_info->kinds[RegisterKind::eRegisterKindDWARF]);
+
+ switch (reg_info->kinds[RegisterKind::eRegisterKindGeneric]) {
+ case LLDB_REGNUM_GENERIC_PC:
+ response.PutCString("generic:pc;");
+ break;
+ case LLDB_REGNUM_GENERIC_SP:
+ response.PutCString("generic:sp;");
+ break;
+ case LLDB_REGNUM_GENERIC_FP:
+ response.PutCString("generic:fp;");
+ break;
+ case LLDB_REGNUM_GENERIC_RA:
+ response.PutCString("generic:ra;");
+ break;
+ case LLDB_REGNUM_GENERIC_FLAGS:
+ response.PutCString("generic:flags;");
+ break;
+ case LLDB_REGNUM_GENERIC_ARG1:
+ response.PutCString("generic:arg1;");
+ break;
+ case LLDB_REGNUM_GENERIC_ARG2:
+ response.PutCString("generic:arg2;");
+ break;
+ case LLDB_REGNUM_GENERIC_ARG3:
+ response.PutCString("generic:arg3;");
+ break;
+ case LLDB_REGNUM_GENERIC_ARG4:
+ response.PutCString("generic:arg4;");
+ break;
+ case LLDB_REGNUM_GENERIC_ARG5:
+ response.PutCString("generic:arg5;");
+ break;
+ case LLDB_REGNUM_GENERIC_ARG6:
+ response.PutCString("generic:arg6;");
+ break;
+ case LLDB_REGNUM_GENERIC_ARG7:
+ response.PutCString("generic:arg7;");
+ break;
+ case LLDB_REGNUM_GENERIC_ARG8:
+ response.PutCString("generic:arg8;");
+ break;
+ default:
+ break;
+ }
+
+ if (reg_info->value_regs && reg_info->value_regs[0] != LLDB_INVALID_REGNUM) {
+ response.PutCString("container-regs:");
+ int i = 0;
+ for (const uint32_t *reg_num = reg_info->value_regs;
+ *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) {
+ if (i > 0)
+ response.PutChar(',');
+ response.Printf("%" PRIx32, *reg_num);
+ }
+ response.PutChar(';');
+ }
+
+ if (reg_info->invalidate_regs && reg_info->invalidate_regs[0]) {
+ response.PutCString("invalidate-regs:");
+ int i = 0;
+ for (const uint32_t *reg_num = reg_info->invalidate_regs;
+ *reg_num != LLDB_INVALID_REGNUM; ++reg_num, ++i) {
+ if (i > 0)
+ response.PutChar(',');
+ response.Printf("%" PRIx32, *reg_num);
+ }
+ response.PutChar(';');
+ }
+
+ if (reg_info->dynamic_size_dwarf_expr_bytes) {
+ const size_t dwarf_opcode_len = reg_info->dynamic_size_dwarf_len;
+ response.PutCString("dynamic_size_dwarf_expr_bytes:");
+ for (uint32_t i = 0; i < dwarf_opcode_len; ++i)
+ response.PutHex8(reg_info->dynamic_size_dwarf_expr_bytes[i]);
+ response.PutChar(';');
+ }
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
-
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s() no process (%s), returning OK", __FUNCTION__, m_debugged_process_sp ? "invalid process id" : "null m_debugged_process_sp");
- return SendOKResponse ();
- }
-
- StreamGDBRemote response;
- response.PutChar ('m');
+GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s() starting thread iteration", __FUNCTION__);
-
- NativeThreadProtocolSP thread_sp;
- uint32_t thread_index;
- for (thread_index = 0, thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index);
- thread_sp;
- ++thread_index, thread_sp = m_debugged_process_sp->GetThreadAtIndex (thread_index))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s() iterated thread %" PRIu32 "(%s, tid=0x%" PRIx64 ")", __FUNCTION__, thread_index, thread_sp ? "is not null" : "null", thread_sp ? thread_sp->GetID () : LLDB_INVALID_THREAD_ID);
- if (thread_index > 0)
- response.PutChar(',');
- response.Printf ("%" PRIx64, thread_sp->GetID ());
- }
-
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s() no process (%s), "
+ "returning OK",
+ __FUNCTION__,
+ m_debugged_process_sp ? "invalid process id"
+ : "null m_debugged_process_sp");
+ return SendOKResponse();
+ }
+
+ StreamGDBRemote response;
+ response.PutChar('m');
+
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s() starting thread iteration",
+ __FUNCTION__);
+
+ NativeThreadProtocolSP thread_sp;
+ uint32_t thread_index;
+ for (thread_index = 0,
+ thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index);
+ thread_sp; ++thread_index,
+ thread_sp = m_debugged_process_sp->GetThreadAtIndex(thread_index)) {
if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s() finished thread iteration", __FUNCTION__);
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s() iterated thread %" PRIu32
+ "(%s, tid=0x%" PRIx64 ")",
+ __FUNCTION__, thread_index, thread_sp ? "is not null" : "null",
+ thread_sp ? thread_sp->GetID() : LLDB_INVALID_THREAD_ID);
+ if (thread_index > 0)
+ response.PutChar(',');
+ response.Printf("%" PRIx64, thread_sp->GetID());
+ }
+
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s() finished thread iteration",
+ __FUNCTION__);
- return SendPacketNoLock(response.GetData(), response.GetSize());
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo (StringExtractorGDBRemote &packet)
-{
- // FIXME for now we return the full thread list in the initial packet and always do nothing here.
- return SendPacketNoLock ("l", 1);
+GDBRemoteCommunicationServerLLGS::Handle_qsThreadInfo(
+ StringExtractorGDBRemote &packet) {
+ // FIXME for now we return the full thread list in the initial packet and
+ // always do nothing here.
+ return SendPacketNoLock("l");
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_p (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
-
- // Parse out the register number from the request.
- packet.SetFilePos (strlen("p"));
- const uint32_t reg_index = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
- if (reg_index == std::numeric_limits<uint32_t>::max ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, could not parse register number from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ());
- return SendErrorResponse (0x15);
- }
-
- // Get the thread to use.
- NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet);
- if (!thread_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no thread available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
-
- // Get the thread's register context.
- NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
- if (!reg_context_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ());
- return SendErrorResponse (0x15);
- }
-
- // Return the end of registers response if we've iterated one past the end of the register set.
- if (reg_index >= reg_context_sp->GetUserRegisterCount ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ());
- return SendErrorResponse (0x15);
- }
-
- const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex(reg_index);
- if (!reg_info)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, requested register %" PRIu32 " returned NULL", __FUNCTION__, reg_index);
- return SendErrorResponse (0x15);
- }
-
- // Build the reginfos response.
- StreamGDBRemote response;
-
- // Retrieve the value
- RegisterValue reg_value;
- Error error = reg_context_sp->ReadRegister (reg_info, reg_value);
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, read of requested register %" PRIu32 " (%s) failed: %s", __FUNCTION__, reg_index, reg_info->name, error.AsCString ());
- return SendErrorResponse (0x15);
- }
-
- const uint8_t *const data = reinterpret_cast<const uint8_t*> (reg_value.GetBytes ());
- if (!data)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to get data bytes from requested register %" PRIu32, __FUNCTION__, reg_index);
- return SendErrorResponse (0x15);
- }
+GDBRemoteCommunicationServerLLGS::Handle_p(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Parse out the register number from the request.
+ packet.SetFilePos(strlen("p"));
+ const uint32_t reg_index =
+ packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
+ if (reg_index == std::numeric_limits<uint32_t>::max()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not "
+ "parse register number from request \"%s\"",
+ __FUNCTION__, packet.GetStringRef().c_str());
+ return SendErrorResponse(0x15);
+ }
+
+ // Get the thread to use.
+ NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet);
+ if (!thread_sp) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no thread available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
+
+ // Get the thread's register context.
+ NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext());
+ if (!reg_context_sp) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64
+ " failed, no register context available for the thread",
+ __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID());
+ return SendErrorResponse(0x15);
+ }
+
+ // Return the end of registers response if we've iterated one past the end of
+ // the register set.
+ if (reg_index >= reg_context_sp->GetUserRegisterCount()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested "
+ "register %" PRIu32 " beyond register count %" PRIu32,
+ __FUNCTION__, reg_index,
+ reg_context_sp->GetUserRegisterCount());
+ return SendErrorResponse(0x15);
+ }
+
+ const RegisterInfo *reg_info =
+ reg_context_sp->GetRegisterInfoAtIndex(reg_index);
+ if (!reg_info) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested "
+ "register %" PRIu32 " returned NULL",
+ __FUNCTION__, reg_index);
+ return SendErrorResponse(0x15);
+ }
+
+ // Build the reginfos response.
+ StreamGDBRemote response;
+
+ // Retrieve the value
+ RegisterValue reg_value;
+ Error error = reg_context_sp->ReadRegister(reg_info, reg_value);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, read of "
+ "requested register %" PRIu32 " (%s) failed: %s",
+ __FUNCTION__, reg_index, reg_info->name, error.AsCString());
+ return SendErrorResponse(0x15);
+ }
+
+ const uint8_t *const data =
+ reinterpret_cast<const uint8_t *>(reg_value.GetBytes());
+ if (!data) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to get data "
+ "bytes from requested register %" PRIu32,
+ __FUNCTION__, reg_index);
+ return SendErrorResponse(0x15);
+ }
- // FIXME flip as needed to get data in big/little endian format for this host.
- for (uint32_t i = 0; i < reg_value.GetByteSize (); ++i)
- response.PutHex8 (data[i]);
+ // FIXME flip as needed to get data in big/little endian format for this host.
+ for (uint32_t i = 0; i < reg_value.GetByteSize(); ++i)
+ response.PutHex8(data[i]);
- return SendPacketNoLock (response.GetData (), response.GetSize ());
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_P (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
-
- // Ensure there is more content.
- if (packet.GetBytesLeft () < 1)
- return SendIllFormedResponse (packet, "Empty P packet");
-
- // Parse out the register number from the request.
- packet.SetFilePos (strlen("P"));
- const uint32_t reg_index = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
- if (reg_index == std::numeric_limits<uint32_t>::max ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, could not parse register number from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ());
- return SendErrorResponse (0x29);
- }
-
- // Note debugserver would send an E30 here.
- if ((packet.GetBytesLeft () < 1) || (packet.GetChar () != '='))
- return SendIllFormedResponse (packet, "P packet missing '=' char after register number");
-
- // Get process architecture.
- ArchSpec process_arch;
- if (!m_debugged_process_sp || !m_debugged_process_sp->GetArchitecture (process_arch))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to retrieve inferior architecture", __FUNCTION__);
- return SendErrorResponse (0x49);
- }
-
- // Parse out the value.
- uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register
- size_t reg_size = packet.GetHexBytesAvail (reg_bytes, sizeof(reg_bytes));
-
- // Get the thread to use.
- NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet);
- if (!thread_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no thread available (thread index 0)", __FUNCTION__);
- return SendErrorResponse (0x28);
- }
-
- // Get the thread's register context.
- NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
- if (!reg_context_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ());
- return SendErrorResponse (0x15);
- }
-
- const RegisterInfo *reg_info = reg_context_sp->GetRegisterInfoAtIndex (reg_index);
- if (!reg_info)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, requested register %" PRIu32 " returned NULL", __FUNCTION__, reg_index);
- return SendErrorResponse (0x48);
- }
-
- // Return the end of registers response if we've iterated one past the end of the register set.
- if (reg_index >= reg_context_sp->GetUserRegisterCount ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, requested register %" PRIu32 " beyond register count %" PRIu32, __FUNCTION__, reg_index, reg_context_sp->GetUserRegisterCount ());
- return SendErrorResponse (0x47);
- }
-
- // The dwarf expression are evaluate on host site
- // which may cause register size to change
- // Hence the reg_size may not be same as reg_info->bytes_size
- if ((reg_size != reg_info->byte_size) && !(reg_info->dynamic_size_dwarf_expr_bytes))
- {
- return SendIllFormedResponse (packet, "P packet register size is incorrect");
- }
-
- // Build the reginfos response.
- StreamGDBRemote response;
-
- RegisterValue reg_value (reg_bytes, reg_size, process_arch.GetByteOrder ());
- Error error = reg_context_sp->WriteRegister (reg_info, reg_value);
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, write of requested register %" PRIu32 " (%s) failed: %s", __FUNCTION__, reg_index, reg_info->name, error.AsCString ());
- return SendErrorResponse (0x32);
- }
+GDBRemoteCommunicationServerLLGS::Handle_P(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Ensure there is more content.
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Empty P packet");
+
+ // Parse out the register number from the request.
+ packet.SetFilePos(strlen("P"));
+ const uint32_t reg_index =
+ packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
+ if (reg_index == std::numeric_limits<uint32_t>::max()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not "
+ "parse register number from request \"%s\"",
+ __FUNCTION__, packet.GetStringRef().c_str());
+ return SendErrorResponse(0x29);
+ }
+
+ // Note debugserver would send an E30 here.
+ if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != '='))
+ return SendIllFormedResponse(
+ packet, "P packet missing '=' char after register number");
+
+ // Get process architecture.
+ ArchSpec process_arch;
+ if (!m_debugged_process_sp ||
+ !m_debugged_process_sp->GetArchitecture(process_arch)) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to retrieve "
+ "inferior architecture",
+ __FUNCTION__);
+ return SendErrorResponse(0x49);
+ }
+
+ // Parse out the value.
+ uint8_t reg_bytes[32]; // big enough to support up to 256 bit ymmN register
+ size_t reg_size = packet.GetHexBytesAvail(reg_bytes);
+
+ // Get the thread to use.
+ NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet);
+ if (!thread_sp) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no thread "
+ "available (thread index 0)",
+ __FUNCTION__);
+ return SendErrorResponse(0x28);
+ }
+
+ // Get the thread's register context.
+ NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext());
+ if (!reg_context_sp) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64
+ " failed, no register context available for the thread",
+ __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID());
+ return SendErrorResponse(0x15);
+ }
+
+ const RegisterInfo *reg_info =
+ reg_context_sp->GetRegisterInfoAtIndex(reg_index);
+ if (!reg_info) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested "
+ "register %" PRIu32 " returned NULL",
+ __FUNCTION__, reg_index);
+ return SendErrorResponse(0x48);
+ }
+
+ // Return the end of registers response if we've iterated one past the end of
+ // the register set.
+ if (reg_index >= reg_context_sp->GetUserRegisterCount()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, requested "
+ "register %" PRIu32 " beyond register count %" PRIu32,
+ __FUNCTION__, reg_index,
+ reg_context_sp->GetUserRegisterCount());
+ return SendErrorResponse(0x47);
+ }
+
+ // The dwarf expression are evaluate on host site
+ // which may cause register size to change
+ // Hence the reg_size may not be same as reg_info->bytes_size
+ if ((reg_size != reg_info->byte_size) &&
+ !(reg_info->dynamic_size_dwarf_expr_bytes)) {
+ return SendIllFormedResponse(packet, "P packet register size is incorrect");
+ }
+
+ // Build the reginfos response.
+ StreamGDBRemote response;
+
+ RegisterValue reg_value(reg_bytes, reg_size, process_arch.GetByteOrder());
+ Error error = reg_context_sp->WriteRegister(reg_info, reg_value);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, write of "
+ "requested register %" PRIu32 " (%s) failed: %s",
+ __FUNCTION__, reg_index, reg_info->name, error.AsCString());
+ return SendErrorResponse(0x32);
+ }
- return SendOKResponse();
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_H (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
-
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
-
- // Parse out which variant of $H is requested.
- packet.SetFilePos (strlen("H"));
- if (packet.GetBytesLeft () < 1)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, H command missing {g,c} variant", __FUNCTION__);
- return SendIllFormedResponse (packet, "H command missing {g,c} variant");
- }
-
- const char h_variant = packet.GetChar ();
- switch (h_variant)
- {
- case 'g':
- break;
-
- case 'c':
- break;
-
- default:
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c", __FUNCTION__, h_variant);
- return SendIllFormedResponse (packet, "H variant unsupported, should be c or g");
- }
-
- // Parse out the thread number.
- // FIXME return a parse success/fail value. All values are valid here.
- const lldb::tid_t tid = packet.GetHexMaxU64 (false, std::numeric_limits<lldb::tid_t>::max ());
+GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
- // Ensure we have the given thread when not specifying -1 (all threads) or 0 (any thread).
- if (tid != LLDB_INVALID_THREAD_ID && tid != 0)
- {
- NativeThreadProtocolSP thread_sp (m_debugged_process_sp->GetThreadByID (tid));
- if (!thread_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 " not found", __FUNCTION__, tid);
- return SendErrorResponse (0x15);
- }
- }
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
+
+ // Parse out which variant of $H is requested.
+ packet.SetFilePos(strlen("H"));
+ if (packet.GetBytesLeft() < 1) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, H command "
+ "missing {g,c} variant",
+ __FUNCTION__);
+ return SendIllFormedResponse(packet, "H command missing {g,c} variant");
+ }
- // Now switch the given thread type.
- switch (h_variant)
- {
- case 'g':
- SetCurrentThreadID (tid);
- break;
+ const char h_variant = packet.GetChar();
+ switch (h_variant) {
+ case 'g':
+ break;
- case 'c':
- SetContinueThreadID (tid);
- break;
+ case 'c':
+ break;
- default:
- assert (false && "unsupported $H variant - shouldn't get here");
- return SendIllFormedResponse (packet, "H variant unsupported, should be c or g");
- }
-
- return SendOKResponse();
+ default:
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, invalid $H variant %c",
+ __FUNCTION__, h_variant);
+ return SendIllFormedResponse(packet,
+ "H variant unsupported, should be c or g");
+ }
+
+ // Parse out the thread number.
+ // FIXME return a parse success/fail value. All values are valid here.
+ const lldb::tid_t tid =
+ packet.GetHexMaxU64(false, std::numeric_limits<lldb::tid_t>::max());
+
+ // Ensure we have the given thread when not specifying -1 (all threads) or 0
+ // (any thread).
+ if (tid != LLDB_INVALID_THREAD_ID && tid != 0) {
+ NativeThreadProtocolSP thread_sp(m_debugged_process_sp->GetThreadByID(tid));
+ if (!thread_sp) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64
+ " not found",
+ __FUNCTION__, tid);
+ return SendErrorResponse(0x15);
+ }
+ }
+
+ // Now switch the given thread type.
+ switch (h_variant) {
+ case 'g':
+ SetCurrentThreadID(tid);
+ break;
+
+ case 'c':
+ SetContinueThreadID(tid);
+ break;
+
+ default:
+ assert(false && "unsupported $H variant - shouldn't get here");
+ return SendIllFormedResponse(packet,
+ "H variant unsupported, should be c or g");
+ }
+
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_I (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+GDBRemoteCommunicationServerLLGS::Handle_I(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
-
- packet.SetFilePos (::strlen("I"));
- char tmp[4096];
- for (;;)
- {
- size_t read = packet.GetHexBytesAvail(tmp, sizeof(tmp));
- if (read == 0)
- {
- break;
- }
- // write directly to stdin *this might block if stdin buffer is full*
- // TODO: enqueue this block in circular buffer and send window size to remote host
- ConnectionStatus status;
- Error error;
- m_stdio_communication.Write(tmp, read, status, &error);
- if (error.Fail())
- {
- return SendErrorResponse (0x15);
- }
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
+
+ packet.SetFilePos(::strlen("I"));
+ uint8_t tmp[4096];
+ for (;;) {
+ size_t read = packet.GetHexBytesAvail(tmp);
+ if (read == 0) {
+ break;
+ }
+ // write directly to stdin *this might block if stdin buffer is full*
+ // TODO: enqueue this block in circular buffer and send window size to
+ // remote host
+ ConnectionStatus status;
+ Error error;
+ m_stdio_communication.Write(tmp, read, status, &error);
+ if (error.Fail()) {
+ return SendErrorResponse(0x15);
}
+ }
- return SendOKResponse();
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_interrupt (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
-
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
-
- // Interrupt the process.
- Error error = m_debugged_process_sp->Interrupt ();
- if (error.Fail ())
- {
- if (log)
- {
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed for process %" PRIu64 ": %s",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- error.AsCString ());
- }
- return SendErrorResponse (GDBRemoteServerError::eErrorResume);
- }
+GDBRemoteCommunicationServerLLGS::Handle_interrupt(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s stopped process %" PRIu64, __FUNCTION__, m_debugged_process_sp->GetID ());
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
+
+ // Interrupt the process.
+ Error error = m_debugged_process_sp->Interrupt();
+ if (error.Fail()) {
+ if (log) {
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed for process %" PRIu64
+ ": %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(), error.AsCString());
+ }
+ return SendErrorResponse(GDBRemoteServerError::eErrorResume);
+ }
+
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s stopped process %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
- // No response required from stop all.
- return PacketResult::Success;
+ // No response required from stop all.
+ return PacketResult::Success;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_memory_read(StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
-
- // Parse out the memory address.
- packet.SetFilePos (strlen("m"));
- if (packet.GetBytesLeft() < 1)
- return SendIllFormedResponse(packet, "Too short m packet");
-
- // Read the address. Punting on validation.
- // FIXME replace with Hex U64 read with no default value that fails on failed read.
- const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
-
- // Validate comma.
- if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
- return SendIllFormedResponse(packet, "Comma sep missing in m packet");
-
- // Get # bytes to read.
- if (packet.GetBytesLeft() < 1)
- return SendIllFormedResponse(packet, "Length missing in m packet");
-
- const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
- if (byte_count == 0)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s nothing to read: zero-length packet", __FUNCTION__);
- return SendOKResponse();
- }
-
- // Allocate the response buffer.
- std::string buf(byte_count, '\0');
- if (buf.empty())
- return SendErrorResponse (0x78);
-
-
- // Retrieve the process memory.
- size_t bytes_read = 0;
- Error error = m_debugged_process_sp->ReadMemoryWithoutTrap(read_addr, &buf[0], byte_count, bytes_read);
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": failed to read. Error: %s", __FUNCTION__, m_debugged_process_sp->GetID (), read_addr, error.AsCString ());
- return SendErrorResponse (0x08);
- }
+GDBRemoteCommunicationServerLLGS::Handle_memory_read(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (bytes_read == 0)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes", __FUNCTION__, m_debugged_process_sp->GetID (), read_addr, byte_count);
- return SendErrorResponse (0x08);
- }
-
- StreamGDBRemote response;
- packet.SetFilePos(0);
- char kind = packet.GetChar('?');
- if (kind == 'x')
- response.PutEscapedBytes(buf.data(), byte_count);
- else
- {
- assert(kind == 'm');
- for (size_t i = 0; i < bytes_read; ++i)
- response.PutHex8(buf[i]);
- }
-
- return SendPacketNoLock(response.GetData(), response.GetSize());
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
+
+ // Parse out the memory address.
+ packet.SetFilePos(strlen("m"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short m packet");
+
+ // Read the address. Punting on validation.
+ // FIXME replace with Hex U64 read with no default value that fails on failed
+ // read.
+ const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
+
+ // Validate comma.
+ if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
+ return SendIllFormedResponse(packet, "Comma sep missing in m packet");
+
+ // Get # bytes to read.
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Length missing in m packet");
+
+ const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
+ if (byte_count == 0) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to read: "
+ "zero-length packet",
+ __FUNCTION__);
+ return SendOKResponse();
+ }
+
+ // Allocate the response buffer.
+ std::string buf(byte_count, '\0');
+ if (buf.empty())
+ return SendErrorResponse(0x78);
+
+ // Retrieve the process memory.
+ size_t bytes_read = 0;
+ Error error = m_debugged_process_sp->ReadMemoryWithoutTrap(
+ read_addr, &buf[0], byte_count, bytes_read);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " mem 0x%" PRIx64 ": failed to read. Error: %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(), read_addr,
+ error.AsCString());
+ return SendErrorResponse(0x08);
+ }
+
+ if (bytes_read == 0) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " mem 0x%" PRIx64 ": read 0 of %" PRIu64 " requested bytes",
+ __FUNCTION__, m_debugged_process_sp->GetID(), read_addr,
+ byte_count);
+ return SendErrorResponse(0x08);
+ }
+
+ StreamGDBRemote response;
+ packet.SetFilePos(0);
+ char kind = packet.GetChar('?');
+ if (kind == 'x')
+ response.PutEscapedBytes(buf.data(), byte_count);
+ else {
+ assert(kind == 'm');
+ for (size_t i = 0; i < bytes_read; ++i)
+ response.PutHex8(buf[i]);
+ }
+
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_M (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
-
- // Parse out the memory address.
- packet.SetFilePos (strlen("M"));
- if (packet.GetBytesLeft() < 1)
- return SendIllFormedResponse(packet, "Too short M packet");
-
- // Read the address. Punting on validation.
- // FIXME replace with Hex U64 read with no default value that fails on failed read.
- const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0);
-
- // Validate comma.
- if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
- return SendIllFormedResponse(packet, "Comma sep missing in M packet");
-
- // Get # bytes to read.
- if (packet.GetBytesLeft() < 1)
- return SendIllFormedResponse(packet, "Length missing in M packet");
+GDBRemoteCommunicationServerLLGS::Handle_M(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
- if (byte_count == 0)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s nothing to write: zero-length packet", __FUNCTION__);
- return PacketResult::Success;
- }
-
- // Validate colon.
- if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':'))
- return SendIllFormedResponse(packet, "Comma sep missing in M packet after byte length");
-
- // Allocate the conversion buffer.
- std::vector<uint8_t> buf(byte_count, 0);
- if (buf.empty())
- return SendErrorResponse (0x78);
-
- // Convert the hex memory write contents to bytes.
- StreamGDBRemote response;
- const uint64_t convert_count = packet.GetHexBytes(&buf[0], byte_count, 0);
- if (convert_count != byte_count)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": asked to write %" PRIu64 " bytes, but only found %" PRIu64 " to convert.", __FUNCTION__, m_debugged_process_sp->GetID (), write_addr, byte_count, convert_count);
- return SendIllFormedResponse (packet, "M content byte length specified did not match hex-encoded content length");
- }
-
- // Write the process memory.
- size_t bytes_written = 0;
- Error error = m_debugged_process_sp->WriteMemory (write_addr, &buf[0], byte_count, bytes_written);
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": failed to write. Error: %s", __FUNCTION__, m_debugged_process_sp->GetID (), write_addr, error.AsCString ());
- return SendErrorResponse (0x09);
- }
-
- if (bytes_written == 0)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " mem 0x%" PRIx64 ": wrote 0 of %" PRIu64 " requested bytes", __FUNCTION__, m_debugged_process_sp->GetID (), write_addr, byte_count);
- return SendErrorResponse (0x09);
- }
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
+
+ // Parse out the memory address.
+ packet.SetFilePos(strlen("M"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short M packet");
+
+ // Read the address. Punting on validation.
+ // FIXME replace with Hex U64 read with no default value that fails on failed
+ // read.
+ const lldb::addr_t write_addr = packet.GetHexMaxU64(false, 0);
+
+ // Validate comma.
+ if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ','))
+ return SendIllFormedResponse(packet, "Comma sep missing in M packet");
+
+ // Get # bytes to read.
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Length missing in M packet");
+
+ const uint64_t byte_count = packet.GetHexMaxU64(false, 0);
+ if (byte_count == 0) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s nothing to write: "
+ "zero-length packet",
+ __FUNCTION__);
+ return PacketResult::Success;
+ }
+
+ // Validate colon.
+ if ((packet.GetBytesLeft() < 1) || (packet.GetChar() != ':'))
+ return SendIllFormedResponse(
+ packet, "Comma sep missing in M packet after byte length");
+
+ // Allocate the conversion buffer.
+ std::vector<uint8_t> buf(byte_count, 0);
+ if (buf.empty())
+ return SendErrorResponse(0x78);
+
+ // Convert the hex memory write contents to bytes.
+ StreamGDBRemote response;
+ const uint64_t convert_count = packet.GetHexBytes(buf, 0);
+ if (convert_count != byte_count) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " mem 0x%" PRIx64 ": asked to write %" PRIu64
+ " bytes, but only found %" PRIu64 " to convert.",
+ __FUNCTION__, m_debugged_process_sp->GetID(), write_addr,
+ byte_count, convert_count);
+ return SendIllFormedResponse(packet, "M content byte length specified did "
+ "not match hex-encoded content "
+ "length");
+ }
+
+ // Write the process memory.
+ size_t bytes_written = 0;
+ Error error = m_debugged_process_sp->WriteMemory(write_addr, &buf[0],
+ byte_count, bytes_written);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " mem 0x%" PRIx64 ": failed to write. Error: %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(), write_addr,
+ error.AsCString());
+ return SendErrorResponse(0x09);
+ }
+
+ if (bytes_written == 0) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " mem 0x%" PRIx64 ": wrote 0 of %" PRIu64 " requested bytes",
+ __FUNCTION__, m_debugged_process_sp->GetID(), write_addr,
+ byte_count);
+ return SendErrorResponse(0x09);
+ }
- return SendOKResponse ();
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // Currently only the NativeProcessProtocol knows if it can handle a qMemoryRegionInfoSupported
- // request, but we're not guaranteed to be attached to a process. For now we'll assume the
- // client only asks this when a process is being debugged.
-
- // Ensure we have a process running; otherwise, we can't figure this out
- // since we won't have a NativeProcessProtocol.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
+GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfoSupported(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Currently only the NativeProcessProtocol knows if it can handle a
+ // qMemoryRegionInfoSupported
+ // request, but we're not guaranteed to be attached to a process. For now
+ // we'll assume the
+ // client only asks this when a process is being debugged.
+
+ // Ensure we have a process running; otherwise, we can't figure this out
+ // since we won't have a NativeProcessProtocol.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
- // Test if we can get any region back when asking for the region around NULL.
- MemoryRegionInfo region_info;
- const Error error = m_debugged_process_sp->GetMemoryRegionInfo (0, region_info);
- if (error.Fail ())
- {
- // We don't support memory region info collection for this NativeProcessProtocol.
- return SendUnimplementedResponse ("");
- }
+ // Test if we can get any region back when asking for the region around NULL.
+ MemoryRegionInfo region_info;
+ const Error error =
+ m_debugged_process_sp->GetMemoryRegionInfo(0, region_info);
+ if (error.Fail()) {
+ // We don't support memory region info collection for this
+ // NativeProcessProtocol.
+ return SendUnimplementedResponse("");
+ }
- return SendOKResponse();
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // Ensure we have a process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
-
- // Parse out the memory address.
- packet.SetFilePos (strlen("qMemoryRegionInfo:"));
- if (packet.GetBytesLeft() < 1)
- return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet");
-
- // Read the address. Punting on validation.
- const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
+GDBRemoteCommunicationServerLLGS::Handle_qMemoryRegionInfo(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- StreamGDBRemote response;
-
- // Get the memory region info for the target address.
- MemoryRegionInfo region_info;
- const Error error = m_debugged_process_sp->GetMemoryRegionInfo (read_addr, region_info);
- if (error.Fail ())
- {
- // Return the error message.
-
- response.PutCString ("error:");
- response.PutCStringAsRawHex8 (error.AsCString ());
- response.PutChar (';');
- }
- else
- {
- // Range start and size.
- response.Printf ("start:%" PRIx64 ";size:%" PRIx64 ";", region_info.GetRange ().GetRangeBase (), region_info.GetRange ().GetByteSize ());
-
- // Permissions.
- if (region_info.GetReadable () ||
- region_info.GetWritable () ||
- region_info.GetExecutable ())
- {
- // Write permissions info.
- response.PutCString ("permissions:");
-
- if (region_info.GetReadable ())
- response.PutChar ('r');
- if (region_info.GetWritable ())
- response.PutChar('w');
- if (region_info.GetExecutable())
- response.PutChar ('x');
-
- response.PutChar (';');
- }
- }
-
- return SendPacketNoLock(response.GetData(), response.GetSize());
+ // Ensure we have a process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
+
+ // Parse out the memory address.
+ packet.SetFilePos(strlen("qMemoryRegionInfo:"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short qMemoryRegionInfo: packet");
+
+ // Read the address. Punting on validation.
+ const lldb::addr_t read_addr = packet.GetHexMaxU64(false, 0);
+
+ StreamGDBRemote response;
+
+ // Get the memory region info for the target address.
+ MemoryRegionInfo region_info;
+ const Error error =
+ m_debugged_process_sp->GetMemoryRegionInfo(read_addr, region_info);
+ if (error.Fail()) {
+ // Return the error message.
+
+ response.PutCString("error:");
+ response.PutCStringAsRawHex8(error.AsCString());
+ response.PutChar(';');
+ } else {
+ // Range start and size.
+ response.Printf("start:%" PRIx64 ";size:%" PRIx64 ";",
+ region_info.GetRange().GetRangeBase(),
+ region_info.GetRange().GetByteSize());
+
+ // Permissions.
+ if (region_info.GetReadable() || region_info.GetWritable() ||
+ region_info.GetExecutable()) {
+ // Write permissions info.
+ response.PutCString("permissions:");
+
+ if (region_info.GetReadable())
+ response.PutChar('r');
+ if (region_info.GetWritable())
+ response.PutChar('w');
+ if (region_info.GetExecutable())
+ response.PutChar('x');
+
+ response.PutChar(';');
+ }
+
+ // Name
+ ConstString name = region_info.GetName();
+ if (name) {
+ response.PutCString("name:");
+ response.PutCStringAsRawHex8(name.AsCString());
+ response.PutChar(';');
+ }
+ }
+
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_Z (StringExtractorGDBRemote &packet)
-{
- // Ensure we have a process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
-
- // Parse out software or hardware breakpoint or watchpoint requested.
- packet.SetFilePos (strlen("Z"));
- if (packet.GetBytesLeft() < 1)
- return SendIllFormedResponse(packet, "Too short Z packet, missing software/hardware specifier");
-
- bool want_breakpoint = true;
- bool want_hardware = false;
- uint32_t watch_flags = 0;
-
- const GDBStoppointType stoppoint_type =
- GDBStoppointType(packet.GetS32 (eStoppointInvalid));
- switch (stoppoint_type)
- {
- case eBreakpointSoftware:
- want_hardware = false; want_breakpoint = true; break;
- case eBreakpointHardware:
- want_hardware = true; want_breakpoint = true; break;
- case eWatchpointWrite:
- watch_flags = 1;
- want_hardware = true; want_breakpoint = false; break;
- case eWatchpointRead:
- watch_flags = 2;
- want_hardware = true; want_breakpoint = false; break;
- case eWatchpointReadWrite:
- watch_flags = 3;
- want_hardware = true; want_breakpoint = false; break;
- case eStoppointInvalid:
- return SendIllFormedResponse(packet, "Z packet had invalid software/hardware specifier");
-
- }
-
- if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
- return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after stoppoint type");
-
- // Parse out the stoppoint address.
- if (packet.GetBytesLeft() < 1)
- return SendIllFormedResponse(packet, "Too short Z packet, missing address");
- const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
-
- if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
- return SendIllFormedResponse(packet, "Malformed Z packet, expecting comma after address");
-
- // Parse out the stoppoint size (i.e. size hint for opcode size).
- const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
- if (size == std::numeric_limits<uint32_t>::max ())
- return SendIllFormedResponse(packet, "Malformed Z packet, failed to parse size argument");
-
- if (want_breakpoint)
- {
- // Try to set the breakpoint.
- const Error error = m_debugged_process_sp->SetBreakpoint (addr, size, want_hardware);
- if (error.Success ())
- return SendOKResponse ();
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
- " failed to set breakpoint: %s",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- error.AsCString ());
- return SendErrorResponse (0x09);
- }
- else
- {
- // Try to set the watchpoint.
- const Error error = m_debugged_process_sp->SetWatchpoint (
- addr, size, watch_flags, want_hardware);
- if (error.Success ())
- return SendOKResponse ();
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
- " failed to set watchpoint: %s",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- error.AsCString ());
- return SendErrorResponse (0x09);
- }
+GDBRemoteCommunicationServerLLGS::Handle_Z(StringExtractorGDBRemote &packet) {
+ // Ensure we have a process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
+
+ // Parse out software or hardware breakpoint or watchpoint requested.
+ packet.SetFilePos(strlen("Z"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(
+ packet, "Too short Z packet, missing software/hardware specifier");
+
+ bool want_breakpoint = true;
+ bool want_hardware = false;
+ uint32_t watch_flags = 0;
+
+ const GDBStoppointType stoppoint_type =
+ GDBStoppointType(packet.GetS32(eStoppointInvalid));
+ switch (stoppoint_type) {
+ case eBreakpointSoftware:
+ want_hardware = false;
+ want_breakpoint = true;
+ break;
+ case eBreakpointHardware:
+ want_hardware = true;
+ want_breakpoint = true;
+ break;
+ case eWatchpointWrite:
+ watch_flags = 1;
+ want_hardware = true;
+ want_breakpoint = false;
+ break;
+ case eWatchpointRead:
+ watch_flags = 2;
+ want_hardware = true;
+ want_breakpoint = false;
+ break;
+ case eWatchpointReadWrite:
+ watch_flags = 3;
+ want_hardware = true;
+ want_breakpoint = false;
+ break;
+ case eStoppointInvalid:
+ return SendIllFormedResponse(
+ packet, "Z packet had invalid software/hardware specifier");
+ }
+
+ if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
+ return SendIllFormedResponse(
+ packet, "Malformed Z packet, expecting comma after stoppoint type");
+
+ // Parse out the stoppoint address.
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short Z packet, missing address");
+ const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
+
+ if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
+ return SendIllFormedResponse(
+ packet, "Malformed Z packet, expecting comma after address");
+
+ // Parse out the stoppoint size (i.e. size hint for opcode size).
+ const uint32_t size =
+ packet.GetHexMaxU32(false, std::numeric_limits<uint32_t>::max());
+ if (size == std::numeric_limits<uint32_t>::max())
+ return SendIllFormedResponse(
+ packet, "Malformed Z packet, failed to parse size argument");
+
+ if (want_breakpoint) {
+ // Try to set the breakpoint.
+ const Error error =
+ m_debugged_process_sp->SetBreakpoint(addr, size, want_hardware);
+ if (error.Success())
+ return SendOKResponse();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " failed to set breakpoint: %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
+ return SendErrorResponse(0x09);
+ } else {
+ // Try to set the watchpoint.
+ const Error error = m_debugged_process_sp->SetWatchpoint(
+ addr, size, watch_flags, want_hardware);
+ if (error.Success())
+ return SendOKResponse();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " failed to set watchpoint: %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
+ return SendErrorResponse(0x09);
+ }
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_z (StringExtractorGDBRemote &packet)
-{
- // Ensure we have a process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
-
- // Parse out software or hardware breakpoint or watchpoint requested.
- packet.SetFilePos (strlen("z"));
- if (packet.GetBytesLeft() < 1)
- return SendIllFormedResponse(packet, "Too short z packet, missing software/hardware specifier");
-
- bool want_breakpoint = true;
-
- const GDBStoppointType stoppoint_type =
- GDBStoppointType(packet.GetS32 (eStoppointInvalid));
- switch (stoppoint_type)
- {
- case eBreakpointHardware: want_breakpoint = true; break;
- case eBreakpointSoftware: want_breakpoint = true; break;
- case eWatchpointWrite: want_breakpoint = false; break;
- case eWatchpointRead: want_breakpoint = false; break;
- case eWatchpointReadWrite: want_breakpoint = false; break;
- default:
- return SendIllFormedResponse(packet, "z packet had invalid software/hardware specifier");
-
- }
-
- if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
- return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after stoppoint type");
-
- // Parse out the stoppoint address.
- if (packet.GetBytesLeft() < 1)
- return SendIllFormedResponse(packet, "Too short z packet, missing address");
- const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
-
- if ((packet.GetBytesLeft() < 1) || packet.GetChar () != ',')
- return SendIllFormedResponse(packet, "Malformed z packet, expecting comma after address");
-
- /*
- // Parse out the stoppoint size (i.e. size hint for opcode size).
- const uint32_t size = packet.GetHexMaxU32 (false, std::numeric_limits<uint32_t>::max ());
- if (size == std::numeric_limits<uint32_t>::max ())
- return SendIllFormedResponse(packet, "Malformed z packet, failed to parse size argument");
- */
-
- if (want_breakpoint)
- {
- // Try to clear the breakpoint.
- const Error error = m_debugged_process_sp->RemoveBreakpoint (addr);
- if (error.Success ())
- return SendOKResponse ();
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
- " failed to remove breakpoint: %s",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- error.AsCString ());
- return SendErrorResponse (0x09);
- }
- else
- {
- // Try to clear the watchpoint.
- const Error error = m_debugged_process_sp->RemoveWatchpoint (addr);
- if (error.Success ())
- return SendOKResponse ();
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
- " failed to remove watchpoint: %s",
- __FUNCTION__,
- m_debugged_process_sp->GetID (),
- error.AsCString ());
- return SendErrorResponse (0x09);
- }
+GDBRemoteCommunicationServerLLGS::Handle_z(StringExtractorGDBRemote &packet) {
+ // Ensure we have a process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
+
+ // Parse out software or hardware breakpoint or watchpoint requested.
+ packet.SetFilePos(strlen("z"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(
+ packet, "Too short z packet, missing software/hardware specifier");
+
+ bool want_breakpoint = true;
+
+ const GDBStoppointType stoppoint_type =
+ GDBStoppointType(packet.GetS32(eStoppointInvalid));
+ switch (stoppoint_type) {
+ case eBreakpointHardware:
+ want_breakpoint = true;
+ break;
+ case eBreakpointSoftware:
+ want_breakpoint = true;
+ break;
+ case eWatchpointWrite:
+ want_breakpoint = false;
+ break;
+ case eWatchpointRead:
+ want_breakpoint = false;
+ break;
+ case eWatchpointReadWrite:
+ want_breakpoint = false;
+ break;
+ default:
+ return SendIllFormedResponse(
+ packet, "z packet had invalid software/hardware specifier");
+ }
+
+ if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
+ return SendIllFormedResponse(
+ packet, "Malformed z packet, expecting comma after stoppoint type");
+
+ // Parse out the stoppoint address.
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet, "Too short z packet, missing address");
+ const lldb::addr_t addr = packet.GetHexMaxU64(false, 0);
+
+ if ((packet.GetBytesLeft() < 1) || packet.GetChar() != ',')
+ return SendIllFormedResponse(
+ packet, "Malformed z packet, expecting comma after address");
+
+ /*
+ // Parse out the stoppoint size (i.e. size hint for opcode size).
+ const uint32_t size = packet.GetHexMaxU32 (false,
+ std::numeric_limits<uint32_t>::max ());
+ if (size == std::numeric_limits<uint32_t>::max ())
+ return SendIllFormedResponse(packet, "Malformed z packet, failed to parse
+ size argument");
+ */
+
+ if (want_breakpoint) {
+ // Try to clear the breakpoint.
+ const Error error = m_debugged_process_sp->RemoveBreakpoint(addr);
+ if (error.Success())
+ return SendOKResponse();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " failed to remove breakpoint: %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
+ return SendErrorResponse(0x09);
+ } else {
+ // Try to clear the watchpoint.
+ const Error error = m_debugged_process_sp->RemoveWatchpoint(addr);
+ if (error.Success())
+ return SendOKResponse();
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " failed to remove watchpoint: %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
+ return SendErrorResponse(0x09);
+ }
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_s (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_THREAD));
-
- // Ensure we have a process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x32);
- }
+GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
- // We first try to use a continue thread id. If any one or any all set, use the current thread.
- // Bail out if we don't have a thread id.
- lldb::tid_t tid = GetContinueThreadID ();
- if (tid == 0 || tid == LLDB_INVALID_THREAD_ID)
- tid = GetCurrentThreadID ();
- if (tid == LLDB_INVALID_THREAD_ID)
- return SendErrorResponse (0x33);
-
- // Double check that we have such a thread.
- // TODO investigate: on MacOSX we might need to do an UpdateThreads () here.
- NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetThreadByID (tid);
- if (!thread_sp || thread_sp->GetID () != tid)
- return SendErrorResponse (0x33);
-
- // Create the step action for the given thread.
- ResumeAction action = { tid, eStateStepping, 0 };
-
- // Setup the actions list.
- ResumeActionList actions;
- actions.Append (action);
-
- // All other threads stop while we're single stepping a thread.
- actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
- Error error = m_debugged_process_sp->Resume (actions);
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " Resume() failed with error: %s", __FUNCTION__, m_debugged_process_sp->GetID (), tid, error.AsCString ());
- return SendErrorResponse(0x49);
- }
+ // Ensure we have a process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x32);
+ }
+
+ // We first try to use a continue thread id. If any one or any all set, use
+ // the current thread.
+ // Bail out if we don't have a thread id.
+ lldb::tid_t tid = GetContinueThreadID();
+ if (tid == 0 || tid == LLDB_INVALID_THREAD_ID)
+ tid = GetCurrentThreadID();
+ if (tid == LLDB_INVALID_THREAD_ID)
+ return SendErrorResponse(0x33);
+
+ // Double check that we have such a thread.
+ // TODO investigate: on MacOSX we might need to do an UpdateThreads () here.
+ NativeThreadProtocolSP thread_sp = m_debugged_process_sp->GetThreadByID(tid);
+ if (!thread_sp || thread_sp->GetID() != tid)
+ return SendErrorResponse(0x33);
+
+ // Create the step action for the given thread.
+ ResumeAction action = {tid, eStateStepping, 0};
+
+ // Setup the actions list.
+ ResumeActionList actions;
+ actions.Append(action);
+
+ // All other threads stop while we're single stepping a thread.
+ actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0);
+ Error error = m_debugged_process_sp->Resume(actions);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " tid %" PRIu64 " Resume() failed with error: %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(), tid,
+ error.AsCString());
+ return SendErrorResponse(0x49);
+ }
- // No response here - the stop or exit will come from the resulting action.
- return PacketResult::Success;
+ // No response here - the stop or exit will come from the resulting action.
+ return PacketResult::Success;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read (StringExtractorGDBRemote &packet)
-{
- // *BSD impls should be able to do this too.
+GDBRemoteCommunicationServerLLGS::Handle_qXfer_auxv_read(
+ StringExtractorGDBRemote &packet) {
+// *BSD impls should be able to do this too.
#if defined(__linux__)
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // Parse out the offset.
- packet.SetFilePos (strlen("qXfer:auxv:read::"));
- if (packet.GetBytesLeft () < 1)
- return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing offset");
-
- const uint64_t auxv_offset = packet.GetHexMaxU64 (false, std::numeric_limits<uint64_t>::max ());
- if (auxv_offset == std::numeric_limits<uint64_t>::max ())
- return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing offset");
-
- // Parse out comma.
- if (packet.GetBytesLeft () < 1 || packet.GetChar () != ',')
- return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing comma after offset");
-
- // Parse out the length.
- const uint64_t auxv_length = packet.GetHexMaxU64 (false, std::numeric_limits<uint64_t>::max ());
- if (auxv_length == std::numeric_limits<uint64_t>::max ())
- return SendIllFormedResponse (packet, "qXfer:auxv:read:: packet missing length");
-
- // Grab the auxv data if we need it.
- if (!m_active_auxv_buffer_sp)
- {
- // Make sure we have a valid process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x10);
- }
-
- // Grab the auxv data.
- m_active_auxv_buffer_sp = Host::GetAuxvData (m_debugged_process_sp->GetID ());
- if (!m_active_auxv_buffer_sp || m_active_auxv_buffer_sp->GetByteSize () == 0)
- {
- // Hmm, no auxv data, call that an error.
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no auxv data retrieved", __FUNCTION__);
- m_active_auxv_buffer_sp.reset ();
- return SendErrorResponse (0x11);
- }
- }
-
- // FIXME find out if/how I lock the stream here.
-
- StreamGDBRemote response;
- bool done_with_buffer = false;
-
- if (auxv_offset >= m_active_auxv_buffer_sp->GetByteSize ())
- {
- // We have nothing left to send. Mark the buffer as complete.
- response.PutChar ('l');
- done_with_buffer = true;
- }
- else
- {
- // Figure out how many bytes are available starting at the given offset.
- const uint64_t bytes_remaining = m_active_auxv_buffer_sp->GetByteSize () - auxv_offset;
-
- // Figure out how many bytes we're going to read.
- const uint64_t bytes_to_read = (auxv_length > bytes_remaining) ? bytes_remaining : auxv_length;
-
- // Mark the response type according to whether we're reading the remainder of the auxv data.
- if (bytes_to_read >= bytes_remaining)
- {
- // There will be nothing left to read after this
- response.PutChar ('l');
- done_with_buffer = true;
- }
- else
- {
- // There will still be bytes to read after this request.
- response.PutChar ('m');
- }
-
- // Now write the data in encoded binary form.
- response.PutEscapedBytes (m_active_auxv_buffer_sp->GetBytes () + auxv_offset, bytes_to_read);
- }
-
- if (done_with_buffer)
- m_active_auxv_buffer_sp.reset ();
-
- return SendPacketNoLock(response.GetData(), response.GetSize());
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Parse out the offset.
+ packet.SetFilePos(strlen("qXfer:auxv:read::"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(packet,
+ "qXfer:auxv:read:: packet missing offset");
+
+ const uint64_t auxv_offset =
+ packet.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
+ if (auxv_offset == std::numeric_limits<uint64_t>::max())
+ return SendIllFormedResponse(packet,
+ "qXfer:auxv:read:: packet missing offset");
+
+ // Parse out comma.
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ',')
+ return SendIllFormedResponse(
+ packet, "qXfer:auxv:read:: packet missing comma after offset");
+
+ // Parse out the length.
+ const uint64_t auxv_length =
+ packet.GetHexMaxU64(false, std::numeric_limits<uint64_t>::max());
+ if (auxv_length == std::numeric_limits<uint64_t>::max())
+ return SendIllFormedResponse(packet,
+ "qXfer:auxv:read:: packet missing length");
+
+ // Grab the auxv data if we need it.
+ if (!m_active_auxv_buffer_sp) {
+ // Make sure we have a valid process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x10);
+ }
+
+ // Grab the auxv data.
+ m_active_auxv_buffer_sp = Host::GetAuxvData(m_debugged_process_sp->GetID());
+ if (!m_active_auxv_buffer_sp ||
+ m_active_auxv_buffer_sp->GetByteSize() == 0) {
+ // Hmm, no auxv data, call that an error.
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, no auxv data "
+ "retrieved",
+ __FUNCTION__);
+ m_active_auxv_buffer_sp.reset();
+ return SendErrorResponse(0x11);
+ }
+ }
+
+ // FIXME find out if/how I lock the stream here.
+
+ StreamGDBRemote response;
+ bool done_with_buffer = false;
+
+ if (auxv_offset >= m_active_auxv_buffer_sp->GetByteSize()) {
+ // We have nothing left to send. Mark the buffer as complete.
+ response.PutChar('l');
+ done_with_buffer = true;
+ } else {
+ // Figure out how many bytes are available starting at the given offset.
+ const uint64_t bytes_remaining =
+ m_active_auxv_buffer_sp->GetByteSize() - auxv_offset;
+
+ // Figure out how many bytes we're going to read.
+ const uint64_t bytes_to_read =
+ (auxv_length > bytes_remaining) ? bytes_remaining : auxv_length;
+
+ // Mark the response type according to whether we're reading the remainder
+ // of the auxv data.
+ if (bytes_to_read >= bytes_remaining) {
+ // There will be nothing left to read after this
+ response.PutChar('l');
+ done_with_buffer = true;
+ } else {
+ // There will still be bytes to read after this request.
+ response.PutChar('m');
+ }
+
+ // Now write the data in encoded binary form.
+ response.PutEscapedBytes(m_active_auxv_buffer_sp->GetBytes() + auxv_offset,
+ bytes_to_read);
+ }
+
+ if (done_with_buffer)
+ m_active_auxv_buffer_sp.reset();
+
+ return SendPacketNoLock(response.GetString());
#else
- return SendUnimplementedResponse ("not implemented on this platform");
+ return SendUnimplementedResponse("not implemented on this platform");
#endif
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
-
- // Move past packet name.
- packet.SetFilePos (strlen ("QSaveRegisterState"));
-
- // Get the thread to use.
- NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet);
- if (!thread_sp)
- {
- if (m_thread_suffix_supported)
- return SendIllFormedResponse (packet, "No thread specified in QSaveRegisterState packet");
- else
- return SendIllFormedResponse (packet, "No thread was is set with the Hg packet");
- }
-
- // Grab the register context for the thread.
- NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
- if (!reg_context_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ());
- return SendErrorResponse (0x15);
- }
-
- // Save registers to a buffer.
- DataBufferSP register_data_sp;
- Error error = reg_context_sp->ReadAllRegisterValues (register_data_sp);
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " failed to save all register values: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ());
- return SendErrorResponse (0x75);
- }
-
- // Allocate a new save id.
- const uint32_t save_id = GetNextSavedRegistersID ();
- assert ((m_saved_registers_map.find (save_id) == m_saved_registers_map.end ()) && "GetNextRegisterSaveID() returned an existing register save id");
+GDBRemoteCommunicationServerLLGS::Handle_QSaveRegisterState(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Move past packet name.
+ packet.SetFilePos(strlen("QSaveRegisterState"));
+
+ // Get the thread to use.
+ NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet);
+ if (!thread_sp) {
+ if (m_thread_suffix_supported)
+ return SendIllFormedResponse(
+ packet, "No thread specified in QSaveRegisterState packet");
+ else
+ return SendIllFormedResponse(packet,
+ "No thread was is set with the Hg packet");
+ }
- // Save the register data buffer under the save id.
- {
- std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
- m_saved_registers_map[save_id] = register_data_sp;
- }
+ // Grab the register context for the thread.
+ NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext());
+ if (!reg_context_sp) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64
+ " failed, no register context available for the thread",
+ __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID());
+ return SendErrorResponse(0x15);
+ }
+
+ // Save registers to a buffer.
+ DataBufferSP register_data_sp;
+ Error error = reg_context_sp->ReadAllRegisterValues(register_data_sp);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " failed to save all register values: %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
+ return SendErrorResponse(0x75);
+ }
+
+ // Allocate a new save id.
+ const uint32_t save_id = GetNextSavedRegistersID();
+ assert((m_saved_registers_map.find(save_id) == m_saved_registers_map.end()) &&
+ "GetNextRegisterSaveID() returned an existing register save id");
+
+ // Save the register data buffer under the save id.
+ {
+ std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
+ m_saved_registers_map[save_id] = register_data_sp;
+ }
- // Write the response.
- StreamGDBRemote response;
- response.Printf ("%" PRIu32, save_id);
- return SendPacketNoLock(response.GetData(), response.GetSize());
+ // Write the response.
+ StreamGDBRemote response;
+ response.Printf("%" PRIu32, save_id);
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
-
- // Parse out save id.
- packet.SetFilePos (strlen ("QRestoreRegisterState:"));
- if (packet.GetBytesLeft () < 1)
- return SendIllFormedResponse (packet, "QRestoreRegisterState packet missing register save id");
-
- const uint32_t save_id = packet.GetU32 (0);
- if (save_id == 0)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s QRestoreRegisterState packet has malformed save id, expecting decimal uint32_t", __FUNCTION__);
- return SendErrorResponse (0x76);
- }
+GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Parse out save id.
+ packet.SetFilePos(strlen("QRestoreRegisterState:"));
+ if (packet.GetBytesLeft() < 1)
+ return SendIllFormedResponse(
+ packet, "QRestoreRegisterState packet missing register save id");
+
+ const uint32_t save_id = packet.GetU32(0);
+ if (save_id == 0) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s QRestoreRegisterState "
+ "packet has malformed save id, expecting decimal uint32_t",
+ __FUNCTION__);
+ return SendErrorResponse(0x76);
+ }
+
+ // Get the thread to use.
+ NativeThreadProtocolSP thread_sp = GetThreadFromSuffix(packet);
+ if (!thread_sp) {
+ if (m_thread_suffix_supported)
+ return SendIllFormedResponse(
+ packet, "No thread specified in QRestoreRegisterState packet");
+ else
+ return SendIllFormedResponse(packet,
+ "No thread was is set with the Hg packet");
+ }
- // Get the thread to use.
- NativeThreadProtocolSP thread_sp = GetThreadFromSuffix (packet);
- if (!thread_sp)
- {
- if (m_thread_suffix_supported)
- return SendIllFormedResponse (packet, "No thread specified in QRestoreRegisterState packet");
- else
- return SendIllFormedResponse (packet, "No thread was is set with the Hg packet");
- }
+ // Grab the register context for the thread.
+ NativeRegisterContextSP reg_context_sp(thread_sp->GetRegisterContext());
+ if (!reg_context_sp) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64
+ " failed, no register context available for the thread",
+ __FUNCTION__, m_debugged_process_sp->GetID(), thread_sp->GetID());
+ return SendErrorResponse(0x15);
+ }
+
+ // Retrieve register state buffer, then remove from the list.
+ DataBufferSP register_data_sp;
+ {
+ std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
- // Grab the register context for the thread.
- NativeRegisterContextSP reg_context_sp (thread_sp->GetRegisterContext ());
- if (!reg_context_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " tid %" PRIu64 " failed, no register context available for the thread", __FUNCTION__, m_debugged_process_sp->GetID (), thread_sp->GetID ());
- return SendErrorResponse (0x15);
+ // Find the register set buffer for the given save id.
+ auto it = m_saved_registers_map.find(save_id);
+ if (it == m_saved_registers_map.end()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " does not have a register set save buffer for id %" PRIu32,
+ __FUNCTION__, m_debugged_process_sp->GetID(), save_id);
+ return SendErrorResponse(0x77);
}
+ register_data_sp = it->second;
- // Retrieve register state buffer, then remove from the list.
- DataBufferSP register_data_sp;
- {
- std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
-
- // Find the register set buffer for the given save id.
- auto it = m_saved_registers_map.find (save_id);
- if (it == m_saved_registers_map.end ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " does not have a register set save buffer for id %" PRIu32, __FUNCTION__, m_debugged_process_sp->GetID (), save_id);
- return SendErrorResponse (0x77);
- }
- register_data_sp = it->second;
-
- // Remove it from the map.
- m_saved_registers_map.erase (it);
- }
+ // Remove it from the map.
+ m_saved_registers_map.erase(it);
+ }
- Error error = reg_context_sp->WriteAllRegisterValues (register_data_sp);
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 " failed to restore all register values: %s", __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ());
- return SendErrorResponse (0x77);
- }
+ Error error = reg_context_sp->WriteAllRegisterValues(register_data_sp);
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64
+ " failed to restore all register values: %s",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
+ return SendErrorResponse(0x77);
+ }
- return SendOKResponse();
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_vAttach (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // Consume the ';' after vAttach.
- packet.SetFilePos (strlen ("vAttach"));
- if (!packet.GetBytesLeft () || packet.GetChar () != ';')
- return SendIllFormedResponse (packet, "vAttach missing expected ';'");
-
- // Grab the PID to which we will attach (assume hex encoding).
- lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID, 16);
- if (pid == LLDB_INVALID_PROCESS_ID)
- return SendIllFormedResponse (packet, "vAttach failed to parse the process id");
-
- // Attempt to attach.
+GDBRemoteCommunicationServerLLGS::Handle_vAttach(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+
+ // Consume the ';' after vAttach.
+ packet.SetFilePos(strlen("vAttach"));
+ if (!packet.GetBytesLeft() || packet.GetChar() != ';')
+ return SendIllFormedResponse(packet, "vAttach missing expected ';'");
+
+ // Grab the PID to which we will attach (assume hex encoding).
+ lldb::pid_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendIllFormedResponse(packet,
+ "vAttach failed to parse the process id");
+
+ // Attempt to attach.
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s attempting to attach to "
+ "pid %" PRIu64,
+ __FUNCTION__, pid);
+
+ Error error = AttachToProcess(pid);
+
+ if (error.Fail()) {
if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s attempting to attach to pid %" PRIu64, __FUNCTION__, pid);
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to attach to "
+ "pid %" PRIu64 ": %s\n",
+ __FUNCTION__, pid, error.AsCString());
+ return SendErrorResponse(0x01);
+ }
- Error error = AttachToProcess (pid);
-
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to attach to pid %" PRIu64 ": %s\n", __FUNCTION__, pid, error.AsCString());
- return SendErrorResponse (0x01);
- }
-
- // Notify we attached by sending a stop packet.
- return SendStopReasonForState (m_debugged_process_sp->GetState ());
+ // Notify we attached by sending a stop packet.
+ return SendStopReasonForState(m_debugged_process_sp->GetState());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_D (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS));
+GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
- StopSTDIOForwarding();
+ StopSTDIOForwarding();
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, no process available", __FUNCTION__);
- return SendErrorResponse (0x15);
- }
-
- lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
-
- // Consume the ';' after D.
- packet.SetFilePos (1);
- if (packet.GetBytesLeft ())
- {
- if (packet.GetChar () != ';')
- return SendIllFormedResponse (packet, "D missing expected ';'");
-
- // Grab the PID from which we will detach (assume hex encoding).
- pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID, 16);
- if (pid == LLDB_INVALID_PROCESS_ID)
- return SendIllFormedResponse (packet, "D failed to parse the process id");
- }
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)) {
+ if (log)
+ log->Printf(
+ "GDBRemoteCommunicationServerLLGS::%s failed, no process available",
+ __FUNCTION__);
+ return SendErrorResponse(0x15);
+ }
+
+ lldb::pid_t pid = LLDB_INVALID_PROCESS_ID;
+
+ // Consume the ';' after D.
+ packet.SetFilePos(1);
+ if (packet.GetBytesLeft()) {
+ if (packet.GetChar() != ';')
+ return SendIllFormedResponse(packet, "D missing expected ';'");
+
+ // Grab the PID from which we will detach (assume hex encoding).
+ pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16);
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendIllFormedResponse(packet, "D failed to parse the process id");
+ }
- if (pid != LLDB_INVALID_PROCESS_ID &&
- m_debugged_process_sp->GetID () != pid)
- {
- return SendIllFormedResponse (packet, "Invalid pid");
- }
+ if (pid != LLDB_INVALID_PROCESS_ID && m_debugged_process_sp->GetID() != pid) {
+ return SendIllFormedResponse(packet, "Invalid pid");
+ }
- const Error error = m_debugged_process_sp->Detach ();
- if (error.Fail ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to detach from pid %" PRIu64 ": %s\n",
- __FUNCTION__, m_debugged_process_sp->GetID (), error.AsCString ());
- return SendErrorResponse (0x01);
- }
+ const Error error = m_debugged_process_sp->Detach();
+ if (error.Fail()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to detach from "
+ "pid %" PRIu64 ": %s\n",
+ __FUNCTION__, m_debugged_process_sp->GetID(),
+ error.AsCString());
+ return SendErrorResponse(0x01);
+ }
- return SendOKResponse ();
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo (StringExtractorGDBRemote &packet)
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
-
- packet.SetFilePos (strlen("qThreadStopInfo"));
- const lldb::tid_t tid = packet.GetHexMaxU32 (false, LLDB_INVALID_THREAD_ID);
- if (tid == LLDB_INVALID_THREAD_ID)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed, could not parse thread id from request \"%s\"", __FUNCTION__, packet.GetStringRef ().c_str ());
- return SendErrorResponse (0x15);
- }
- return SendStopReplyPacketForThread (tid);
+GDBRemoteCommunicationServerLLGS::Handle_qThreadStopInfo(
+ StringExtractorGDBRemote &packet) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ packet.SetFilePos(strlen("qThreadStopInfo"));
+ const lldb::tid_t tid = packet.GetHexMaxU32(false, LLDB_INVALID_THREAD_ID);
+ if (tid == LLDB_INVALID_THREAD_ID) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed, could not "
+ "parse thread id from request \"%s\"",
+ __FUNCTION__, packet.GetStringRef().c_str());
+ return SendErrorResponse(0x15);
+ }
+ return SendStopReplyPacketForThread(tid);
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo (StringExtractorGDBRemote &)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
-
- // Ensure we have a debugged process.
- if (!m_debugged_process_sp || (m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID))
- return SendErrorResponse (50);
-
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid %" PRIu64,
+GDBRemoteCommunicationServerLLGS::Handle_jThreadsInfo(
+ StringExtractorGDBRemote &) {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD));
+
+ // Ensure we have a debugged process.
+ if (!m_debugged_process_sp ||
+ (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+ return SendErrorResponse(50);
+
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s preparing packet for pid "
+ "%" PRIu64,
__FUNCTION__, m_debugged_process_sp->GetID());
+ StreamString response;
+ const bool threads_with_valid_stop_info_only = false;
+ JSONArray::SP threads_array_sp = GetJSONThreadsInfo(
+ *m_debugged_process_sp, threads_with_valid_stop_info_only);
+ if (!threads_array_sp) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s failed to prepare a "
+ "packet for pid %" PRIu64,
+ __FUNCTION__, m_debugged_process_sp->GetID());
+ return SendErrorResponse(52);
+ }
- StreamString response;
- const bool threads_with_valid_stop_info_only = false;
- JSONArray::SP threads_array_sp = GetJSONThreadsInfo(*m_debugged_process_sp,
- threads_with_valid_stop_info_only);
- if (! threads_array_sp)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s failed to prepare a packet for pid %" PRIu64,
- __FUNCTION__, m_debugged_process_sp->GetID());
- return SendErrorResponse(52);
- }
-
- threads_array_sp->Write(response);
- StreamGDBRemote escaped_response;
- escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
- return SendPacketNoLock (escaped_response.GetData(), escaped_response.GetSize());
+ threads_array_sp->Write(response);
+ StreamGDBRemote escaped_response;
+ escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
+ return SendPacketNoLock(escaped_response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet)
-{
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp ||
- m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)
- return SendErrorResponse (68);
-
- packet.SetFilePos(strlen("qWatchpointSupportInfo"));
- if (packet.GetBytesLeft() == 0)
- return SendOKResponse();
- if (packet.GetChar() != ':')
- return SendErrorResponse(67);
+GDBRemoteCommunicationServerLLGS::Handle_qWatchpointSupportInfo(
+ StringExtractorGDBRemote &packet) {
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(68);
+
+ packet.SetFilePos(strlen("qWatchpointSupportInfo"));
+ if (packet.GetBytesLeft() == 0)
+ return SendOKResponse();
+ if (packet.GetChar() != ':')
+ return SendErrorResponse(67);
- uint32_t num = m_debugged_process_sp->GetMaxWatchpoints();
- StreamGDBRemote response;
- response.Printf ("num:%d;", num);
- return SendPacketNoLock(response.GetData(), response.GetSize());
+ uint32_t num = m_debugged_process_sp->GetMaxWatchpoints();
+ StreamGDBRemote response;
+ response.Printf("num:%d;", num);
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress (StringExtractorGDBRemote &packet)
-{
- // Fail if we don't have a current process.
- if (!m_debugged_process_sp ||
- m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)
- return SendErrorResponse(67);
+GDBRemoteCommunicationServerLLGS::Handle_qFileLoadAddress(
+ StringExtractorGDBRemote &packet) {
+ // Fail if we don't have a current process.
+ if (!m_debugged_process_sp ||
+ m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(67);
- packet.SetFilePos(strlen("qFileLoadAddress:"));
- if (packet.GetBytesLeft() == 0)
- return SendErrorResponse(68);
+ packet.SetFilePos(strlen("qFileLoadAddress:"));
+ if (packet.GetBytesLeft() == 0)
+ return SendErrorResponse(68);
- std::string file_name;
- packet.GetHexByteString(file_name);
+ std::string file_name;
+ packet.GetHexByteString(file_name);
- lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
- Error error = m_debugged_process_sp->GetFileLoadAddress(file_name, file_load_address);
- if (error.Fail())
- return SendErrorResponse(69);
+ lldb::addr_t file_load_address = LLDB_INVALID_ADDRESS;
+ Error error =
+ m_debugged_process_sp->GetFileLoadAddress(file_name, file_load_address);
+ if (error.Fail())
+ return SendErrorResponse(69);
- if (file_load_address == LLDB_INVALID_ADDRESS)
- return SendErrorResponse(1); // File not loaded
+ if (file_load_address == LLDB_INVALID_ADDRESS)
+ return SendErrorResponse(1); // File not loaded
- StreamGDBRemote response;
- response.PutHex64(file_load_address);
- return SendPacketNoLock(response.GetData(), response.GetSize());
-}
-
-void
-GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection ()
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-
- // Tell the stdio connection to shut down.
- if (m_stdio_communication.IsConnected())
- {
- auto connection = m_stdio_communication.GetConnection();
- if (connection)
- {
- Error error;
- connection->Disconnect (&error);
-
- if (error.Success ())
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s disconnect process terminal stdio - SUCCESS", __FUNCTION__);
- }
- else
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s disconnect process terminal stdio - FAIL: %s", __FUNCTION__, error.AsCString ());
- }
- }
- }
+ StreamGDBRemote response;
+ response.PutHex64(file_load_address);
+ return SendPacketNoLock(response.GetString());
}
+void GDBRemoteCommunicationServerLLGS::MaybeCloseInferiorTerminalConnection() {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
-NativeThreadProtocolSP
-GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix (StringExtractorGDBRemote &packet)
-{
- NativeThreadProtocolSP thread_sp;
+ // Tell the stdio connection to shut down.
+ if (m_stdio_communication.IsConnected()) {
+ auto connection = m_stdio_communication.GetConnection();
+ if (connection) {
+ Error error;
+ connection->Disconnect(&error);
- // We have no thread if we don't have a process.
- if (!m_debugged_process_sp || m_debugged_process_sp->GetID () == LLDB_INVALID_PROCESS_ID)
- return thread_sp;
-
- // If the client hasn't asked for thread suffix support, there will not be a thread suffix.
- // Use the current thread in that case.
- if (!m_thread_suffix_supported)
- {
- const lldb::tid_t current_tid = GetCurrentThreadID ();
- if (current_tid == LLDB_INVALID_THREAD_ID)
- return thread_sp;
- else if (current_tid == 0)
- {
- // Pick a thread.
- return m_debugged_process_sp->GetThreadAtIndex (0);
- }
- else
- return m_debugged_process_sp->GetThreadByID (current_tid);
+ if (error.Success()) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process "
+ "terminal stdio - SUCCESS",
+ __FUNCTION__);
+ } else {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s disconnect process "
+ "terminal stdio - FAIL: %s",
+ __FUNCTION__, error.AsCString());
+ }
}
+ }
+}
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+NativeThreadProtocolSP GDBRemoteCommunicationServerLLGS::GetThreadFromSuffix(
+ StringExtractorGDBRemote &packet) {
+ NativeThreadProtocolSP thread_sp;
- // Parse out the ';'.
- if (packet.GetBytesLeft () < 1 || packet.GetChar () != ';')
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse error: expected ';' prior to start of thread suffix: packet contents = '%s'", __FUNCTION__, packet.GetStringRef ().c_str ());
- return thread_sp;
- }
+ // We have no thread if we don't have a process.
+ if (!m_debugged_process_sp ||
+ m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID)
+ return thread_sp;
- if (!packet.GetBytesLeft ())
- return thread_sp;
+ // If the client hasn't asked for thread suffix support, there will not be a
+ // thread suffix.
+ // Use the current thread in that case.
+ if (!m_thread_suffix_supported) {
+ const lldb::tid_t current_tid = GetCurrentThreadID();
+ if (current_tid == LLDB_INVALID_THREAD_ID)
+ return thread_sp;
+ else if (current_tid == 0) {
+ // Pick a thread.
+ return m_debugged_process_sp->GetThreadAtIndex(0);
+ } else
+ return m_debugged_process_sp->GetThreadByID(current_tid);
+ }
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_THREAD));
+
+ // Parse out the ';'.
+ if (packet.GetBytesLeft() < 1 || packet.GetChar() != ';') {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
+ "error: expected ';' prior to start of thread suffix: packet "
+ "contents = '%s'",
+ __FUNCTION__, packet.GetStringRef().c_str());
+ return thread_sp;
+ }
- // Parse out thread: portion.
- if (strncmp (packet.Peek (), "thread:", strlen("thread:")) != 0)
- {
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse error: expected 'thread:' but not found, packet contents = '%s'", __FUNCTION__, packet.GetStringRef ().c_str ());
- return thread_sp;
- }
- packet.SetFilePos (packet.GetFilePos () + strlen("thread:"));
- const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
- if (tid != 0)
- return m_debugged_process_sp->GetThreadByID (tid);
+ if (!packet.GetBytesLeft())
+ return thread_sp;
+ // Parse out thread: portion.
+ if (strncmp(packet.Peek(), "thread:", strlen("thread:")) != 0) {
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s gdb-remote parse "
+ "error: expected 'thread:' but not found, packet contents = "
+ "'%s'",
+ __FUNCTION__, packet.GetStringRef().c_str());
return thread_sp;
+ }
+ packet.SetFilePos(packet.GetFilePos() + strlen("thread:"));
+ const lldb::tid_t tid = packet.GetHexMaxU64(false, 0);
+ if (tid != 0)
+ return m_debugged_process_sp->GetThreadByID(tid);
+
+ return thread_sp;
}
-lldb::tid_t
-GDBRemoteCommunicationServerLLGS::GetCurrentThreadID () const
-{
- if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID)
- {
- // Use whatever the debug process says is the current thread id
- // since the protocol either didn't specify or specified we want
- // any/all threads marked as the current thread.
- if (!m_debugged_process_sp)
- return LLDB_INVALID_THREAD_ID;
- return m_debugged_process_sp->GetCurrentThreadID ();
- }
- // Use the specific current thread id set by the gdb remote protocol.
- return m_current_tid;
+lldb::tid_t GDBRemoteCommunicationServerLLGS::GetCurrentThreadID() const {
+ if (m_current_tid == 0 || m_current_tid == LLDB_INVALID_THREAD_ID) {
+ // Use whatever the debug process says is the current thread id
+ // since the protocol either didn't specify or specified we want
+ // any/all threads marked as the current thread.
+ if (!m_debugged_process_sp)
+ return LLDB_INVALID_THREAD_ID;
+ return m_debugged_process_sp->GetCurrentThreadID();
+ }
+ // Use the specific current thread id set by the gdb remote protocol.
+ return m_current_tid;
}
-uint32_t
-GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID ()
-{
- std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
- return m_next_saved_registers_id++;
+uint32_t GDBRemoteCommunicationServerLLGS::GetNextSavedRegistersID() {
+ std::lock_guard<std::mutex> guard(m_saved_registers_mutex);
+ return m_next_saved_registers_id++;
}
-void
-GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData ()
-{
- Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS|GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s()", __FUNCTION__);
+void GDBRemoteCommunicationServerLLGS::ClearProcessSpecificData() {
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s()", __FUNCTION__);
- // Clear any auxv cached data.
- // *BSD impls should be able to do this too.
+// Clear any auxv cached data.
+// *BSD impls should be able to do this too.
#if defined(__linux__)
- if (log)
- log->Printf ("GDBRemoteCommunicationServerLLGS::%s clearing auxv buffer (previously %s)",
- __FUNCTION__,
- m_active_auxv_buffer_sp ? "was set" : "was not set");
- m_active_auxv_buffer_sp.reset ();
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerLLGS::%s clearing auxv buffer "
+ "(previously %s)",
+ __FUNCTION__,
+ m_active_auxv_buffer_sp ? "was set" : "was not set");
+ m_active_auxv_buffer_sp.reset();
#endif
}
FileSpec
-GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string& module_path,
- const ArchSpec& arch)
-{
- if (m_debugged_process_sp)
- {
- FileSpec file_spec;
- if (m_debugged_process_sp->GetLoadedModuleFileSpec(module_path.c_str(), file_spec).Success())
- {
- if (file_spec.Exists())
- return file_spec;
- }
- }
-
- return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch);
+GDBRemoteCommunicationServerLLGS::FindModuleFile(const std::string &module_path,
+ const ArchSpec &arch) {
+ if (m_debugged_process_sp) {
+ FileSpec file_spec;
+ if (m_debugged_process_sp
+ ->GetLoadedModuleFileSpec(module_path.c_str(), file_spec)
+ .Success()) {
+ if (file_spec.Exists())
+ return file_spec;
+ }
+ }
+
+ return GDBRemoteCommunicationServerCommon::FindModuleFile(module_path, arch);
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
index caf6eb3..fa52cda 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -16,10 +16,10 @@
#include <unordered_map>
// Other libraries and framework includes
-#include "lldb/lldb-private-forward.h"
#include "lldb/Core/Communication.h"
-#include "lldb/Host/common/NativeProcessProtocol.h"
#include "lldb/Host/MainLoop.h"
+#include "lldb/Host/common/NativeProcessProtocol.h"
+#include "lldb/lldb-private-forward.h"
// Project includes
#include "GDBRemoteCommunicationServerCommon.h"
@@ -32,282 +32,220 @@ namespace process_gdb_remote {
class ProcessGDBRemote;
-class GDBRemoteCommunicationServerLLGS :
- public GDBRemoteCommunicationServerCommon,
- public NativeProcessProtocol::NativeDelegate
-{
+class GDBRemoteCommunicationServerLLGS
+ : public GDBRemoteCommunicationServerCommon,
+ public NativeProcessProtocol::NativeDelegate {
public:
- //------------------------------------------------------------------
- // Constructors and Destructors
- //------------------------------------------------------------------
- GDBRemoteCommunicationServerLLGS(MainLoop &mainloop);
-
- //------------------------------------------------------------------
- /// Specify the program to launch and its arguments.
- ///
- /// @param[in] args
- /// The command line to launch.
- ///
- /// @param[in] argc
- /// The number of elements in the args array of cstring pointers.
- ///
- /// @return
- /// An Error object indicating the success or failure of making
- /// the setting.
- //------------------------------------------------------------------
- Error
- SetLaunchArguments (const char *const args[], int argc);
-
- //------------------------------------------------------------------
- /// Specify the launch flags for the process.
- ///
- /// @param[in] launch_flags
- /// The launch flags to use when launching this process.
- ///
- /// @return
- /// An Error object indicating the success or failure of making
- /// the setting.
- //------------------------------------------------------------------
- Error
- SetLaunchFlags (unsigned int launch_flags);
-
- //------------------------------------------------------------------
- /// Launch a process with the current launch settings.
- ///
- /// This method supports running an lldb-gdbserver or similar
- /// server in a situation where the startup code has been provided
- /// with all the information for a child process to be launched.
- ///
- /// @return
- /// An Error object indicating the success or failure of the
- /// launch.
- //------------------------------------------------------------------
- Error
- LaunchProcess () override;
-
- //------------------------------------------------------------------
- /// Attach to a process.
- ///
- /// This method supports attaching llgs to a process accessible via the
- /// configured Platform.
- ///
- /// @return
- /// An Error object indicating the success or failure of the
- /// attach operation.
- //------------------------------------------------------------------
- Error
- AttachToProcess (lldb::pid_t pid);
-
- //------------------------------------------------------------------
- // NativeProcessProtocol::NativeDelegate overrides
- //------------------------------------------------------------------
- void
- InitializeDelegate (NativeProcessProtocol *process) override;
-
- void
- ProcessStateChanged (NativeProcessProtocol *process, lldb::StateType state) override;
-
- void
- DidExec (NativeProcessProtocol *process) override;
-
- Error
- InitializeConnection (std::unique_ptr<Connection> &&connection);
+ //------------------------------------------------------------------
+ // Constructors and Destructors
+ //------------------------------------------------------------------
+ GDBRemoteCommunicationServerLLGS(MainLoop &mainloop);
+
+ //------------------------------------------------------------------
+ /// Specify the program to launch and its arguments.
+ ///
+ /// @param[in] args
+ /// The command line to launch.
+ ///
+ /// @param[in] argc
+ /// The number of elements in the args array of cstring pointers.
+ ///
+ /// @return
+ /// An Error object indicating the success or failure of making
+ /// the setting.
+ //------------------------------------------------------------------
+ Error SetLaunchArguments(const char *const args[], int argc);
+
+ //------------------------------------------------------------------
+ /// Specify the launch flags for the process.
+ ///
+ /// @param[in] launch_flags
+ /// The launch flags to use when launching this process.
+ ///
+ /// @return
+ /// An Error object indicating the success or failure of making
+ /// the setting.
+ //------------------------------------------------------------------
+ Error SetLaunchFlags(unsigned int launch_flags);
+
+ //------------------------------------------------------------------
+ /// Launch a process with the current launch settings.
+ ///
+ /// This method supports running an lldb-gdbserver or similar
+ /// server in a situation where the startup code has been provided
+ /// with all the information for a child process to be launched.
+ ///
+ /// @return
+ /// An Error object indicating the success or failure of the
+ /// launch.
+ //------------------------------------------------------------------
+ Error LaunchProcess() override;
+
+ //------------------------------------------------------------------
+ /// Attach to a process.
+ ///
+ /// This method supports attaching llgs to a process accessible via the
+ /// configured Platform.
+ ///
+ /// @return
+ /// An Error object indicating the success or failure of the
+ /// attach operation.
+ //------------------------------------------------------------------
+ Error AttachToProcess(lldb::pid_t pid);
+
+ //------------------------------------------------------------------
+ // NativeProcessProtocol::NativeDelegate overrides
+ //------------------------------------------------------------------
+ void InitializeDelegate(NativeProcessProtocol *process) override;
+
+ void ProcessStateChanged(NativeProcessProtocol *process,
+ lldb::StateType state) override;
+
+ void DidExec(NativeProcessProtocol *process) override;
+
+ Error InitializeConnection(std::unique_ptr<Connection> &&connection);
protected:
- MainLoop &m_mainloop;
- MainLoop::ReadHandleUP m_network_handle_up;
- lldb::tid_t m_current_tid;
- lldb::tid_t m_continue_tid;
- std::recursive_mutex m_debugged_process_mutex;
- NativeProcessProtocolSP m_debugged_process_sp;
+ MainLoop &m_mainloop;
+ MainLoop::ReadHandleUP m_network_handle_up;
+ lldb::tid_t m_current_tid;
+ lldb::tid_t m_continue_tid;
+ std::recursive_mutex m_debugged_process_mutex;
+ NativeProcessProtocolSP m_debugged_process_sp;
- Communication m_stdio_communication;
- MainLoop::ReadHandleUP m_stdio_handle_up;
+ Communication m_stdio_communication;
+ MainLoop::ReadHandleUP m_stdio_handle_up;
- lldb::StateType m_inferior_prev_state;
- lldb::DataBufferSP m_active_auxv_buffer_sp;
- std::mutex m_saved_registers_mutex;
- std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
- uint32_t m_next_saved_registers_id;
- bool m_handshake_completed : 1;
+ lldb::StateType m_inferior_prev_state;
+ lldb::DataBufferSP m_active_auxv_buffer_sp;
+ std::mutex m_saved_registers_mutex;
+ std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
+ uint32_t m_next_saved_registers_id;
+ bool m_handshake_completed : 1;
- PacketResult
- SendONotification (const char *buffer, uint32_t len);
+ PacketResult SendONotification(const char *buffer, uint32_t len);
- PacketResult
- SendWResponse (NativeProcessProtocol *process);
+ PacketResult SendWResponse(NativeProcessProtocol *process);
- PacketResult
- SendStopReplyPacketForThread (lldb::tid_t tid);
+ PacketResult SendStopReplyPacketForThread(lldb::tid_t tid);
- PacketResult
- SendStopReasonForState (lldb::StateType process_state);
+ PacketResult SendStopReasonForState(lldb::StateType process_state);
- PacketResult
- Handle_k (StringExtractorGDBRemote &packet);
+ PacketResult Handle_k(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qProcessInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qProcessInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qC (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qC(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QSetDisableASLR (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QSetDisableASLR(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QSetWorkingDir(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qGetWorkingDir (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_C (StringExtractorGDBRemote &packet);
+ PacketResult Handle_C(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_c (StringExtractorGDBRemote &packet);
+ PacketResult Handle_c(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vCont (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vCont(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vCont_actions (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vCont_actions(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_stop_reason (StringExtractorGDBRemote &packet);
+ PacketResult Handle_stop_reason(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qRegisterInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qRegisterInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qfThreadInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qfThreadInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qsThreadInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qsThreadInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_p (StringExtractorGDBRemote &packet);
+ PacketResult Handle_p(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_P (StringExtractorGDBRemote &packet);
+ PacketResult Handle_P(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_H (StringExtractorGDBRemote &packet);
+ PacketResult Handle_H(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_I (StringExtractorGDBRemote &packet);
+ PacketResult Handle_I(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_interrupt (StringExtractorGDBRemote &packet);
+ PacketResult Handle_interrupt(StringExtractorGDBRemote &packet);
- // Handles $m and $x packets.
- PacketResult
- Handle_memory_read (StringExtractorGDBRemote &packet);
+ // Handles $m and $x packets.
+ PacketResult Handle_memory_read(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_M (StringExtractorGDBRemote &packet);
+ PacketResult Handle_M(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qMemoryRegionInfoSupported (StringExtractorGDBRemote &packet);
+ PacketResult
+ Handle_qMemoryRegionInfoSupported(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qMemoryRegionInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qMemoryRegionInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_Z (StringExtractorGDBRemote &packet);
+ PacketResult Handle_Z(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_z (StringExtractorGDBRemote &packet);
+ PacketResult Handle_z(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_s (StringExtractorGDBRemote &packet);
+ PacketResult Handle_s(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qXfer_auxv_read (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qXfer_auxv_read(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QSaveRegisterState (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QRestoreRegisterState (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_vAttach (StringExtractorGDBRemote &packet);
+ PacketResult Handle_vAttach(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_D (StringExtractorGDBRemote &packet);
+ PacketResult Handle_D(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qThreadStopInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qThreadStopInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_jThreadsInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_jThreadsInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qWatchpointSupportInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qWatchpointSupportInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qFileLoadAddress (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qFileLoadAddress(StringExtractorGDBRemote &packet);
- void
- SetCurrentThreadID (lldb::tid_t tid);
+ void SetCurrentThreadID(lldb::tid_t tid);
- lldb::tid_t
- GetCurrentThreadID () const;
+ lldb::tid_t GetCurrentThreadID() const;
- void
- SetContinueThreadID (lldb::tid_t tid);
+ void SetContinueThreadID(lldb::tid_t tid);
- lldb::tid_t
- GetContinueThreadID () const { return m_continue_tid; }
+ lldb::tid_t GetContinueThreadID() const { return m_continue_tid; }
- Error
- SetSTDIOFileDescriptor (int fd);
+ Error SetSTDIOFileDescriptor(int fd);
- FileSpec
- FindModuleFile (const std::string& module_path, const ArchSpec& arch) override;
+ FileSpec FindModuleFile(const std::string &module_path,
+ const ArchSpec &arch) override;
private:
- void
- HandleInferiorState_Exited (NativeProcessProtocol *process);
+ void HandleInferiorState_Exited(NativeProcessProtocol *process);
- void
- HandleInferiorState_Stopped (NativeProcessProtocol *process);
+ void HandleInferiorState_Stopped(NativeProcessProtocol *process);
- NativeThreadProtocolSP
- GetThreadFromSuffix (StringExtractorGDBRemote &packet);
+ NativeThreadProtocolSP GetThreadFromSuffix(StringExtractorGDBRemote &packet);
- uint32_t
- GetNextSavedRegistersID ();
+ uint32_t GetNextSavedRegistersID();
- void
- MaybeCloseInferiorTerminalConnection ();
+ void MaybeCloseInferiorTerminalConnection();
- void
- ClearProcessSpecificData ();
+ void ClearProcessSpecificData();
- void
- RegisterPacketHandlers ();
+ void RegisterPacketHandlers();
- void
- DataAvailableCallback ();
+ void DataAvailableCallback();
- void
- SendProcessOutput ();
+ void SendProcessOutput();
- void
- StartSTDIOForwarding();
+ void StartSTDIOForwarding();
- void
- StopSTDIOForwarding();
+ void StopSTDIOForwarding();
- //------------------------------------------------------------------
- // For GDBRemoteCommunicationServerLLGS only
- //------------------------------------------------------------------
- DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServerLLGS);
+ //------------------------------------------------------------------
+ // For GDBRemoteCommunicationServerLLGS only
+ //------------------------------------------------------------------
+ DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServerLLGS);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_GDBRemoteCommunicationServerLLGS_h_
+#endif // liblldb_GDBRemoteCommunicationServerLLGS_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
index d6900c2..1106974 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.cpp
@@ -13,8 +13,8 @@
// C Includes
// C++ Includes
-#include <cstring>
#include <chrono>
+#include <cstring>
#include <mutex>
#include <sstream>
@@ -47,549 +47,525 @@ using namespace lldb_private::process_gdb_remote;
//----------------------------------------------------------------------
// GDBRemoteCommunicationServerPlatform constructor
//----------------------------------------------------------------------
-GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol,
- const char *socket_scheme)
- : GDBRemoteCommunicationServerCommon("gdb-remote.server", "gdb-remote.server.rx_packet"),
- m_socket_protocol(socket_protocol),
- m_socket_scheme(socket_scheme),
- m_spawned_pids_mutex(),
- m_port_map(),
- m_port_offset(0)
-{
- m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
- m_pending_gdb_server.port = 0;
-
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qC,
- &GDBRemoteCommunicationServerPlatform::Handle_qC);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
- &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
- &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
- &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
- &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
- &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
- &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
- RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
- &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
-
- RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
- [this](StringExtractorGDBRemote packet, Error &error, bool &interrupt, bool &quit) {
- error.SetErrorString("interrupt received");
- interrupt = true;
- return PacketResult::Success;
- });
+GDBRemoteCommunicationServerPlatform::GDBRemoteCommunicationServerPlatform(
+ const Socket::SocketProtocol socket_protocol, const char *socket_scheme)
+ : GDBRemoteCommunicationServerCommon("gdb-remote.server",
+ "gdb-remote.server.rx_packet"),
+ m_socket_protocol(socket_protocol), m_socket_scheme(socket_scheme),
+ m_spawned_pids_mutex(), m_port_map(), m_port_offset(0) {
+ m_pending_gdb_server.pid = LLDB_INVALID_PROCESS_ID;
+ m_pending_gdb_server.port = 0;
+
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qC,
+ &GDBRemoteCommunicationServerPlatform::Handle_qC);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qGetWorkingDir,
+ &GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qLaunchGDBServer,
+ &GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qQueryGDBServer,
+ &GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qKillSpawnedProcess,
+ &GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_qProcessInfo,
+ &GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_QSetWorkingDir,
+ &GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir);
+ RegisterMemberFunctionHandler(
+ StringExtractorGDBRemote::eServerPacketType_jSignalsInfo,
+ &GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo);
+
+ RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_interrupt,
+ [this](StringExtractorGDBRemote packet, Error &error,
+ bool &interrupt, bool &quit) {
+ error.SetErrorString("interrupt received");
+ interrupt = true;
+ return PacketResult::Success;
+ });
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform()
-{
-}
-
-Error
-GDBRemoteCommunicationServerPlatform::LaunchGDBServer(const lldb_private::Args& args,
- std::string hostname,
- lldb::pid_t& pid,
- uint16_t& port,
- std::string& socket_name)
-{
- if (port == UINT16_MAX)
- port = GetNextAvailablePort();
-
- // Spawn a new thread to accept the port that gets bound after
- // binding to port 0 (zero).
-
- // ignore the hostname send from the remote end, just use the ip address
- // that we're currently communicating with as the hostname
-
- // Spawn a debugserver and try to get the port it listens to.
- ProcessLaunchInfo debugserver_launch_info;
- if (hostname.empty())
- hostname = "127.0.0.1";
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
- if (log)
- log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
-
- // Do not run in a new session so that it can not linger after the
- // platform closes.
- debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
- debugserver_launch_info.SetMonitorProcessCallback(
- std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1), false);
-
- std::string platform_scheme;
- std::string platform_ip;
- int platform_port;
- std::string platform_path;
- bool ok = UriParser::Parse(GetConnection()->GetURI().c_str(), platform_scheme, platform_ip, platform_port, platform_path);
- UNUSED_IF_ASSERT_DISABLED(ok);
- assert(ok);
-
- std::ostringstream url;
- // debugserver does not accept the URL scheme prefix.
+GDBRemoteCommunicationServerPlatform::~GDBRemoteCommunicationServerPlatform() {}
+
+Error GDBRemoteCommunicationServerPlatform::LaunchGDBServer(
+ const lldb_private::Args &args, std::string hostname, lldb::pid_t &pid,
+ uint16_t &port, std::string &socket_name) {
+ if (port == UINT16_MAX)
+ port = GetNextAvailablePort();
+
+ // Spawn a new thread to accept the port that gets bound after
+ // binding to port 0 (zero).
+
+ // ignore the hostname send from the remote end, just use the ip address
+ // that we're currently communicating with as the hostname
+
+ // Spawn a debugserver and try to get the port it listens to.
+ ProcessLaunchInfo debugserver_launch_info;
+ if (hostname.empty())
+ hostname = "127.0.0.1";
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("Launching debugserver with: %s:%u...", hostname.c_str(), port);
+
+ // Do not run in a new session so that it can not linger after the
+ // platform closes.
+ debugserver_launch_info.SetLaunchInSeparateProcessGroup(false);
+ debugserver_launch_info.SetMonitorProcessCallback(
+ std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
+ this, std::placeholders::_1),
+ false);
+
+ llvm::StringRef platform_scheme;
+ llvm::StringRef platform_ip;
+ int platform_port;
+ llvm::StringRef platform_path;
+ bool ok = UriParser::Parse(GetConnection()->GetURI(), platform_scheme,
+ platform_ip, platform_port, platform_path);
+ UNUSED_IF_ASSERT_DISABLED(ok);
+ assert(ok);
+
+ std::ostringstream url;
+// debugserver does not accept the URL scheme prefix.
#if !defined(__APPLE__)
- url << m_socket_scheme << "://";
+ url << m_socket_scheme << "://";
#endif
- uint16_t* port_ptr = &port;
- if (m_socket_protocol == Socket::ProtocolTcp)
- url << platform_ip << ":" << port;
- else
- {
- socket_name = GetDomainSocketPath("gdbserver").GetPath();
- url << socket_name;
- port_ptr = nullptr;
- }
-
- Error error = StartDebugserverProcess (url.str().c_str(),
- nullptr,
- debugserver_launch_info,
- port_ptr,
- args);
-
- pid = debugserver_launch_info.GetProcessID();
- if (pid != LLDB_INVALID_PROCESS_ID)
- {
- std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
- m_spawned_pids.insert(pid);
- if (port > 0)
- AssociatePortWithProcess(port, pid);
- }
- else
- {
- if (port > 0)
- FreePort(port);
- }
- return error;
+ uint16_t *port_ptr = &port;
+ if (m_socket_protocol == Socket::ProtocolTcp)
+ url << platform_ip.str() << ":" << port;
+ else {
+ socket_name = GetDomainSocketPath("gdbserver").GetPath();
+ url << socket_name;
+ port_ptr = nullptr;
+ }
+
+ Error error = StartDebugserverProcess(
+ url.str().c_str(), nullptr, debugserver_launch_info, port_ptr, &args, -1);
+
+ pid = debugserver_launch_info.GetProcessID();
+ if (pid != LLDB_INVALID_PROCESS_ID) {
+ std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
+ m_spawned_pids.insert(pid);
+ if (port > 0)
+ AssociatePortWithProcess(port, pid);
+ } else {
+ if (port > 0)
+ FreePort(port);
+ }
+ return error;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet)
-{
+GDBRemoteCommunicationServerPlatform::Handle_qLaunchGDBServer(
+ StringExtractorGDBRemote &packet) {
#ifdef _WIN32
- return SendErrorResponse(9);
+ return SendErrorResponse(9);
#else
- // Spawn a local debugserver as a platform so we can then attach or launch
- // a process...
-
- Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ // Spawn a local debugserver as a platform so we can then attach or launch
+ // a process...
+
+ Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerPlatform::%s() called",
+ __FUNCTION__);
+
+ ConnectionFileDescriptor file_conn;
+ std::string hostname;
+ packet.SetFilePos(::strlen("qLaunchGDBServer;"));
+ llvm::StringRef name;
+ llvm::StringRef value;
+ uint16_t port = UINT16_MAX;
+ while (packet.GetNameColonValue(name, value)) {
+ if (name.equals("host"))
+ hostname = value;
+ else if (name.equals("port"))
+ value.getAsInteger(0, port);
+ }
+
+ lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ std::string socket_name;
+ Error error =
+ LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
+ if (error.Fail()) {
if (log)
- log->Printf ("GDBRemoteCommunicationServerPlatform::%s() called", __FUNCTION__);
-
- ConnectionFileDescriptor file_conn;
- std::string hostname;
- packet.SetFilePos(::strlen ("qLaunchGDBServer;"));
- std::string name;
- std::string value;
- uint16_t port = UINT16_MAX;
- while (packet.GetNameColonValue(name, value))
- {
- if (name.compare ("host") == 0)
- hostname.swap(value);
- else if (name.compare ("port") == 0)
- port = StringConvert::ToUInt32(value.c_str(), 0, 0);
- }
-
- lldb::pid_t debugserver_pid = LLDB_INVALID_PROCESS_ID;
- std::string socket_name;
- Error error = LaunchGDBServer(Args(), hostname, debugserver_pid, port, socket_name);
- if (error.Fail())
- {
- if (log)
- log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver launch failed: %s", __FUNCTION__, error.AsCString ());
- return SendErrorResponse(9);
- }
-
- if (log)
- log->Printf ("GDBRemoteCommunicationServerPlatform::%s() debugserver launched successfully as pid %" PRIu64, __FUNCTION__, debugserver_pid);
-
- StreamGDBRemote response;
- response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid, port + m_port_offset);
- if (!socket_name.empty())
- {
- response.PutCString("socket_name:");
- response.PutCStringAsRawHex8(socket_name.c_str());
- response.PutChar(';');
- }
-
- PacketResult packet_result = SendPacketNoLock(response.GetData(), response.GetSize());
- if (packet_result != PacketResult::Success)
- {
- if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
- ::kill (debugserver_pid, SIGINT);
- }
- return packet_result;
+ log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
+ "launch failed: %s",
+ __FUNCTION__, error.AsCString());
+ return SendErrorResponse(9);
+ }
+
+ if (log)
+ log->Printf("GDBRemoteCommunicationServerPlatform::%s() debugserver "
+ "launched successfully as pid %" PRIu64,
+ __FUNCTION__, debugserver_pid);
+
+ StreamGDBRemote response;
+ response.Printf("pid:%" PRIu64 ";port:%u;", debugserver_pid,
+ port + m_port_offset);
+ if (!socket_name.empty()) {
+ response.PutCString("socket_name:");
+ response.PutCStringAsRawHex8(socket_name.c_str());
+ response.PutChar(';');
+ }
+
+ PacketResult packet_result = SendPacketNoLock(response.GetString());
+ if (packet_result != PacketResult::Success) {
+ if (debugserver_pid != LLDB_INVALID_PROCESS_ID)
+ ::kill(debugserver_pid, SIGINT);
+ }
+ return packet_result;
#endif
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer (StringExtractorGDBRemote &packet)
-{
- if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
- return SendErrorResponse(4);
-
- JSONObject::SP server_sp = std::make_shared<JSONObject>();
- server_sp->SetObject("port", std::make_shared<JSONNumber>(m_pending_gdb_server.port));
- if (!m_pending_gdb_server.socket_name.empty())
- server_sp->SetObject("socket_name",
- std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
-
- JSONArray server_list;
- server_list.AppendObject(server_sp);
-
- StreamGDBRemote response;
- server_list.Write(response);
-
- StreamGDBRemote escaped_response;
- escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
- return SendPacketNoLock(escaped_response.GetData(), escaped_response.GetSize());
+GDBRemoteCommunicationServerPlatform::Handle_qQueryGDBServer(
+ StringExtractorGDBRemote &packet) {
+ if (m_pending_gdb_server.pid == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(4);
+
+ JSONObject::SP server_sp = std::make_shared<JSONObject>();
+ server_sp->SetObject("port",
+ std::make_shared<JSONNumber>(m_pending_gdb_server.port));
+ if (!m_pending_gdb_server.socket_name.empty())
+ server_sp->SetObject(
+ "socket_name",
+ std::make_shared<JSONString>(m_pending_gdb_server.socket_name.c_str()));
+
+ JSONArray server_list;
+ server_list.AppendObject(server_sp);
+
+ StreamGDBRemote response;
+ server_list.Write(response);
+
+ StreamGDBRemote escaped_response;
+ escaped_response.PutEscapedBytes(response.GetString().data(),
+ response.GetSize());
+ return SendPacketNoLock(escaped_response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos(::strlen ("qKillSpawnedProcess:"));
+GDBRemoteCommunicationServerPlatform::Handle_qKillSpawnedProcess(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("qKillSpawnedProcess:"));
- lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
+ lldb::pid_t pid = packet.GetU64(LLDB_INVALID_PROCESS_ID);
- // verify that we know anything about this pid.
- // Scope for locker
- {
- std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- {
- // not a pid we know about
- return SendErrorResponse (10);
- }
+ // verify that we know anything about this pid.
+ // Scope for locker
+ {
+ std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
+ // not a pid we know about
+ return SendErrorResponse(10);
}
+ }
- // go ahead and attempt to kill the spawned process
- if (KillSpawnedProcess (pid))
- return SendOKResponse ();
- else
- return SendErrorResponse (11);
+ // go ahead and attempt to kill the spawned process
+ if (KillSpawnedProcess(pid))
+ return SendOKResponse();
+ else
+ return SendErrorResponse(11);
}
-bool
-GDBRemoteCommunicationServerPlatform::KillSpawnedProcess (lldb::pid_t pid)
-{
- // make sure we know about this process
- {
- std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return false;
- }
+bool GDBRemoteCommunicationServerPlatform::KillSpawnedProcess(lldb::pid_t pid) {
+ // make sure we know about this process
+ {
+ std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return false;
+ }
- // first try a SIGTERM (standard kill)
- Host::Kill (pid, SIGTERM);
+ // first try a SIGTERM (standard kill)
+ Host::Kill(pid, SIGTERM);
- // check if that worked
- for (size_t i=0; i<10; ++i)
+ // check if that worked
+ for (size_t i = 0; i < 10; ++i) {
{
- {
- std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- {
- // it is now killed
- return true;
- }
- }
- usleep (10000);
+ std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
+ // it is now killed
+ return true;
+ }
}
+ usleep(10000);
+ }
- // check one more time after the final usleep
- {
- std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return true;
- }
+ // check one more time after the final usleep
+ {
+ std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
- // the launched process still lives. Now try killing it again,
- // this time with an unblockable signal.
- Host::Kill (pid, SIGKILL);
+ // the launched process still lives. Now try killing it again,
+ // this time with an unblockable signal.
+ Host::Kill(pid, SIGKILL);
- for (size_t i=0; i<10; ++i)
+ for (size_t i = 0; i < 10; ++i) {
{
- {
- std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- {
- // it is now killed
- return true;
- }
- }
- usleep (10000);
+ std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end()) {
+ // it is now killed
+ return true;
+ }
}
+ usleep(10000);
+ }
- // check one more time after the final usleep
- // Scope for locker
- {
- std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
- if (m_spawned_pids.find(pid) == m_spawned_pids.end())
- return true;
- }
+ // check one more time after the final usleep
+ // Scope for locker
+ {
+ std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
+ if (m_spawned_pids.find(pid) == m_spawned_pids.end())
+ return true;
+ }
- // no luck - the process still lives
- return false;
+ // no luck - the process still lives
+ return false;
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo (StringExtractorGDBRemote &packet)
-{
- lldb::pid_t pid = m_process_launch_info.GetProcessID ();
- m_process_launch_info.Clear ();
+GDBRemoteCommunicationServerPlatform::Handle_qProcessInfo(
+ StringExtractorGDBRemote &packet) {
+ lldb::pid_t pid = m_process_launch_info.GetProcessID();
+ m_process_launch_info.Clear();
- if (pid == LLDB_INVALID_PROCESS_ID)
- return SendErrorResponse (1);
+ if (pid == LLDB_INVALID_PROCESS_ID)
+ return SendErrorResponse(1);
- ProcessInstanceInfo proc_info;
- if (!Host::GetProcessInfo (pid, proc_info))
- return SendErrorResponse (1);
+ ProcessInstanceInfo proc_info;
+ if (!Host::GetProcessInfo(pid, proc_info))
+ return SendErrorResponse(1);
- StreamString response;
- CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
- return SendPacketNoLock (response.GetData (), response.GetSize ());
+ StreamString response;
+ CreateProcessInfoResponse_DebugServerStyle(proc_info, response);
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir (StringExtractorGDBRemote &packet)
-{
- // If this packet is sent to a platform, then change the current working directory
-
- char cwd[PATH_MAX];
- if (getcwd(cwd, sizeof(cwd)) == NULL)
- return SendErrorResponse(errno);
-
- StreamString response;
- response.PutBytesAsRawHex8(cwd, strlen(cwd));
- return SendPacketNoLock(response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerPlatform::Handle_qGetWorkingDir(
+ StringExtractorGDBRemote &packet) {
+ // If this packet is sent to a platform, then change the current working
+ // directory
+
+ char cwd[PATH_MAX];
+ if (getcwd(cwd, sizeof(cwd)) == NULL)
+ return SendErrorResponse(errno);
+
+ StreamString response;
+ response.PutBytesAsRawHex8(cwd, strlen(cwd));
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir (StringExtractorGDBRemote &packet)
-{
- packet.SetFilePos (::strlen ("QSetWorkingDir:"));
- std::string path;
- packet.GetHexByteString (path);
-
- // If this packet is sent to a platform, then change the current working directory
- if (::chdir(path.c_str()) != 0)
- return SendErrorResponse (errno);
- return SendOKResponse ();
+GDBRemoteCommunicationServerPlatform::Handle_QSetWorkingDir(
+ StringExtractorGDBRemote &packet) {
+ packet.SetFilePos(::strlen("QSetWorkingDir:"));
+ std::string path;
+ packet.GetHexByteString(path);
+
+ // If this packet is sent to a platform, then change the current working
+ // directory
+ if (::chdir(path.c_str()) != 0)
+ return SendErrorResponse(errno);
+ return SendOKResponse();
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerPlatform::Handle_qC (StringExtractorGDBRemote &packet)
-{
- // NOTE: lldb should now be using qProcessInfo for process IDs. This path here
- // should not be used. It is reporting process id instead of thread id. The
- // correct answer doesn't seem to make much sense for lldb-platform.
- // CONSIDER: flip to "unsupported".
- lldb::pid_t pid = m_process_launch_info.GetProcessID();
-
- StreamString response;
- response.Printf("QC%" PRIx64, pid);
-
- // If we launch a process and this GDB server is acting as a platform,
- // then we need to clear the process launch state so we can start
- // launching another process. In order to launch a process a bunch or
- // packets need to be sent: environment packets, working directory,
- // disable ASLR, and many more settings. When we launch a process we
- // then need to know when to clear this information. Currently we are
- // selecting the 'qC' packet as that packet which seems to make the most
- // sense.
- if (pid != LLDB_INVALID_PROCESS_ID)
- {
- m_process_launch_info.Clear();
- }
-
- return SendPacketNoLock (response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerPlatform::Handle_qC(
+ StringExtractorGDBRemote &packet) {
+ // NOTE: lldb should now be using qProcessInfo for process IDs. This path
+ // here
+ // should not be used. It is reporting process id instead of thread id. The
+ // correct answer doesn't seem to make much sense for lldb-platform.
+ // CONSIDER: flip to "unsupported".
+ lldb::pid_t pid = m_process_launch_info.GetProcessID();
+
+ StreamString response;
+ response.Printf("QC%" PRIx64, pid);
+
+ // If we launch a process and this GDB server is acting as a platform,
+ // then we need to clear the process launch state so we can start
+ // launching another process. In order to launch a process a bunch or
+ // packets need to be sent: environment packets, working directory,
+ // disable ASLR, and many more settings. When we launch a process we
+ // then need to know when to clear this information. Currently we are
+ // selecting the 'qC' packet as that packet which seems to make the most
+ // sense.
+ if (pid != LLDB_INVALID_PROCESS_ID) {
+ m_process_launch_info.Clear();
+ }
+
+ return SendPacketNoLock(response.GetString());
}
GDBRemoteCommunication::PacketResult
-GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(StringExtractorGDBRemote &packet)
-{
- StructuredData::Array signal_array;
-
- const auto &signals = Host::GetUnixSignals();
- for (auto signo = signals->GetFirstSignalNumber();
- signo != LLDB_INVALID_SIGNAL_NUMBER;
- signo = signals->GetNextSignalNumber(signo))
- {
- auto dictionary = std::make_shared<StructuredData::Dictionary>();
-
- dictionary->AddIntegerItem("signo", signo);
- dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
-
- bool suppress, stop, notify;
- signals->GetSignalInfo(signo, suppress, stop, notify);
- dictionary->AddBooleanItem("suppress", suppress);
- dictionary->AddBooleanItem("stop", stop);
- dictionary->AddBooleanItem("notify", notify);
-
- signal_array.Push(dictionary);
- }
-
- StreamString response;
- signal_array.Dump(response);
- return SendPacketNoLock(response.GetData(), response.GetSize());
+GDBRemoteCommunicationServerPlatform::Handle_jSignalsInfo(
+ StringExtractorGDBRemote &packet) {
+ StructuredData::Array signal_array;
+
+ const auto &signals = Host::GetUnixSignals();
+ for (auto signo = signals->GetFirstSignalNumber();
+ signo != LLDB_INVALID_SIGNAL_NUMBER;
+ signo = signals->GetNextSignalNumber(signo)) {
+ auto dictionary = std::make_shared<StructuredData::Dictionary>();
+
+ dictionary->AddIntegerItem("signo", signo);
+ dictionary->AddStringItem("name", signals->GetSignalAsCString(signo));
+
+ bool suppress, stop, notify;
+ signals->GetSignalInfo(signo, suppress, stop, notify);
+ dictionary->AddBooleanItem("suppress", suppress);
+ dictionary->AddBooleanItem("stop", stop);
+ dictionary->AddBooleanItem("notify", notify);
+
+ signal_array.Push(dictionary);
+ }
+
+ StreamString response;
+ signal_array.Dump(response);
+ return SendPacketNoLock(response.GetString());
}
-bool
-GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped (lldb::pid_t pid)
-{
- std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
- FreePortForProcess(pid);
- m_spawned_pids.erase(pid);
- return true;
+bool GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped(
+ lldb::pid_t pid) {
+ std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
+ FreePortForProcess(pid);
+ m_spawned_pids.erase(pid);
+ return true;
}
-Error
-GDBRemoteCommunicationServerPlatform::LaunchProcess ()
-{
- if (!m_process_launch_info.GetArguments ().GetArgumentCount ())
- return Error ("%s: no process command line specified to launch", __FUNCTION__);
-
- // specify the process monitor if not already set. This should
- // generally be what happens since we need to reap started
- // processes.
- if (!m_process_launch_info.GetMonitorProcessCallback ())
- m_process_launch_info.SetMonitorProcessCallback(
- std::bind(&GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped, this, std::placeholders::_1),
- false);
-
- Error error = Host::LaunchProcess(m_process_launch_info);
- if (!error.Success ())
- {
- fprintf (stderr, "%s: failed to launch executable %s", __FUNCTION__, m_process_launch_info.GetArguments ().GetArgumentAtIndex (0));
- return error;
- }
+Error GDBRemoteCommunicationServerPlatform::LaunchProcess() {
+ if (!m_process_launch_info.GetArguments().GetArgumentCount())
+ return Error("%s: no process command line specified to launch",
+ __FUNCTION__);
+
+ // specify the process monitor if not already set. This should
+ // generally be what happens since we need to reap started
+ // processes.
+ if (!m_process_launch_info.GetMonitorProcessCallback())
+ m_process_launch_info.SetMonitorProcessCallback(
+ std::bind(
+ &GDBRemoteCommunicationServerPlatform::DebugserverProcessReaped,
+ this, std::placeholders::_1),
+ false);
+
+ Error error = Host::LaunchProcess(m_process_launch_info);
+ if (!error.Success()) {
+ fprintf(stderr, "%s: failed to launch executable %s", __FUNCTION__,
+ m_process_launch_info.GetArguments().GetArgumentAtIndex(0));
+ return error;
+ }
- printf ("Launched '%s' as process %" PRIu64 "...\n", m_process_launch_info.GetArguments ().GetArgumentAtIndex (0), m_process_launch_info.GetProcessID());
+ printf("Launched '%s' as process %" PRIu64 "...\n",
+ m_process_launch_info.GetArguments().GetArgumentAtIndex(0),
+ m_process_launch_info.GetProcessID());
- // add to list of spawned processes. On an lldb-gdbserver, we
- // would expect there to be only one.
- const auto pid = m_process_launch_info.GetProcessID();
- if (pid != LLDB_INVALID_PROCESS_ID)
- {
- // add to spawned pids
- std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
- m_spawned_pids.insert(pid);
- }
+ // add to list of spawned processes. On an lldb-gdbserver, we
+ // would expect there to be only one.
+ const auto pid = m_process_launch_info.GetProcessID();
+ if (pid != LLDB_INVALID_PROCESS_ID) {
+ // add to spawned pids
+ std::lock_guard<std::recursive_mutex> guard(m_spawned_pids_mutex);
+ m_spawned_pids.insert(pid);
+ }
- return error;
+ return error;
}
-void
-GDBRemoteCommunicationServerPlatform::SetPortMap (PortMap &&port_map)
-{
- m_port_map = port_map;
+void GDBRemoteCommunicationServerPlatform::SetPortMap(PortMap &&port_map) {
+ m_port_map = port_map;
}
-uint16_t
-GDBRemoteCommunicationServerPlatform::GetNextAvailablePort ()
-{
- if (m_port_map.empty())
- return 0; // Bind to port zero and get a port, we didn't have any limitations
+uint16_t GDBRemoteCommunicationServerPlatform::GetNextAvailablePort() {
+ if (m_port_map.empty())
+ return 0; // Bind to port zero and get a port, we didn't have any
+ // limitations
- for (auto &pair : m_port_map)
- {
- if (pair.second == LLDB_INVALID_PROCESS_ID)
- {
- pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
- return pair.first;
- }
+ for (auto &pair : m_port_map) {
+ if (pair.second == LLDB_INVALID_PROCESS_ID) {
+ pair.second = ~(lldb::pid_t)LLDB_INVALID_PROCESS_ID;
+ return pair.first;
}
- return UINT16_MAX;
+ }
+ return UINT16_MAX;
}
-bool
-GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess (uint16_t port, lldb::pid_t pid)
-{
- PortMap::iterator pos = m_port_map.find(port);
- if (pos != m_port_map.end())
- {
- pos->second = pid;
- return true;
- }
- return false;
+bool GDBRemoteCommunicationServerPlatform::AssociatePortWithProcess(
+ uint16_t port, lldb::pid_t pid) {
+ PortMap::iterator pos = m_port_map.find(port);
+ if (pos != m_port_map.end()) {
+ pos->second = pid;
+ return true;
+ }
+ return false;
}
-bool
-GDBRemoteCommunicationServerPlatform::FreePort (uint16_t port)
-{
- PortMap::iterator pos = m_port_map.find(port);
- if (pos != m_port_map.end())
- {
- pos->second = LLDB_INVALID_PROCESS_ID;
- return true;
- }
- return false;
+bool GDBRemoteCommunicationServerPlatform::FreePort(uint16_t port) {
+ PortMap::iterator pos = m_port_map.find(port);
+ if (pos != m_port_map.end()) {
+ pos->second = LLDB_INVALID_PROCESS_ID;
+ return true;
+ }
+ return false;
}
-bool
-GDBRemoteCommunicationServerPlatform::FreePortForProcess (lldb::pid_t pid)
-{
- if (!m_port_map.empty())
- {
- for (auto &pair : m_port_map)
- {
- if (pair.second == pid)
- {
- pair.second = LLDB_INVALID_PROCESS_ID;
- return true;
- }
- }
+bool GDBRemoteCommunicationServerPlatform::FreePortForProcess(lldb::pid_t pid) {
+ if (!m_port_map.empty()) {
+ for (auto &pair : m_port_map) {
+ if (pair.second == pid) {
+ pair.second = LLDB_INVALID_PROCESS_ID;
+ return true;
+ }
}
- return false;
+ }
+ return false;
}
-const FileSpec&
-GDBRemoteCommunicationServerPlatform::GetDomainSocketDir()
-{
- static FileSpec g_domainsocket_dir;
- static std::once_flag g_once_flag;
-
- std::call_once(g_once_flag, []() {
- const char* domainsocket_dir_env = ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
- if (domainsocket_dir_env != nullptr)
- g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
- else
- HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
- });
-
- return g_domainsocket_dir;
+const FileSpec &GDBRemoteCommunicationServerPlatform::GetDomainSocketDir() {
+ static FileSpec g_domainsocket_dir;
+ static std::once_flag g_once_flag;
+
+ std::call_once(g_once_flag, []() {
+ const char *domainsocket_dir_env =
+ ::getenv("LLDB_DEBUGSERVER_DOMAINSOCKET_DIR");
+ if (domainsocket_dir_env != nullptr)
+ g_domainsocket_dir = FileSpec(domainsocket_dir_env, false);
+ else
+ HostInfo::GetLLDBPath(ePathTypeLLDBTempSystemDir, g_domainsocket_dir);
+ });
+
+ return g_domainsocket_dir;
}
FileSpec
-GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char* prefix)
-{
- llvm::SmallString<PATH_MAX> socket_path;
- llvm::SmallString<PATH_MAX> socket_name((llvm::StringRef(prefix) + ".%%%%%%").str());
+GDBRemoteCommunicationServerPlatform::GetDomainSocketPath(const char *prefix) {
+ llvm::SmallString<PATH_MAX> socket_path;
+ llvm::SmallString<PATH_MAX> socket_name(
+ (llvm::StringRef(prefix) + ".%%%%%%").str());
- FileSpec socket_path_spec(GetDomainSocketDir());
- socket_path_spec.AppendPathComponent(socket_name.c_str());
+ FileSpec socket_path_spec(GetDomainSocketDir());
+ socket_path_spec.AppendPathComponent(socket_name.c_str());
- llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
- return FileSpec(socket_path.c_str(), false);
+ llvm::sys::fs::createUniqueFile(socket_path_spec.GetCString(), socket_path);
+ return FileSpec(socket_path.c_str(), false);
}
-void
-GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset)
-{
- m_port_offset = port_offset;
+void GDBRemoteCommunicationServerPlatform::SetPortOffset(uint16_t port_offset) {
+ m_port_offset = port_offset;
}
-void
-GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(lldb::pid_t pid,
- uint16_t port,
- const std::string& socket_name)
-{
- m_pending_gdb_server.pid = pid;
- m_pending_gdb_server.port = port;
- m_pending_gdb_server.socket_name = socket_name;
+void GDBRemoteCommunicationServerPlatform::SetPendingGdbServer(
+ lldb::pid_t pid, uint16_t port, const std::string &socket_name) {
+ m_pending_gdb_server.pid = pid;
+ m_pending_gdb_server.port = port;
+ m_pending_gdb_server.socket_name = socket_name;
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
index 1f4d08c..472d86e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerPlatform.h
@@ -24,110 +24,90 @@
namespace lldb_private {
namespace process_gdb_remote {
-class GDBRemoteCommunicationServerPlatform :
- public GDBRemoteCommunicationServerCommon
-{
+class GDBRemoteCommunicationServerPlatform
+ : public GDBRemoteCommunicationServerCommon {
public:
- typedef std::map<uint16_t, lldb::pid_t> PortMap;
+ typedef std::map<uint16_t, lldb::pid_t> PortMap;
- GDBRemoteCommunicationServerPlatform(const Socket::SocketProtocol socket_protocol,
- const char* socket_scheme);
+ GDBRemoteCommunicationServerPlatform(
+ const Socket::SocketProtocol socket_protocol, const char *socket_scheme);
- ~GDBRemoteCommunicationServerPlatform() override;
+ ~GDBRemoteCommunicationServerPlatform() override;
- Error
- LaunchProcess () override;
+ Error LaunchProcess() override;
- // Set both ports to zero to let the platform automatically bind to
- // a port chosen by the OS.
- void
- SetPortMap (PortMap &&port_map);
+ // Set both ports to zero to let the platform automatically bind to
+ // a port chosen by the OS.
+ void SetPortMap(PortMap &&port_map);
- //----------------------------------------------------------------------
- // If we are using a port map where we can only use certain ports,
- // get the next available port.
- //
- // If we are using a port map and we are out of ports, return UINT16_MAX
- //
- // If we aren't using a port map, return 0 to indicate we should bind to
- // port 0 and then figure out which port we used.
- //----------------------------------------------------------------------
- uint16_t
- GetNextAvailablePort ();
+ //----------------------------------------------------------------------
+ // If we are using a port map where we can only use certain ports,
+ // get the next available port.
+ //
+ // If we are using a port map and we are out of ports, return UINT16_MAX
+ //
+ // If we aren't using a port map, return 0 to indicate we should bind to
+ // port 0 and then figure out which port we used.
+ //----------------------------------------------------------------------
+ uint16_t GetNextAvailablePort();
- bool
- AssociatePortWithProcess (uint16_t port, lldb::pid_t pid);
+ bool AssociatePortWithProcess(uint16_t port, lldb::pid_t pid);
- bool
- FreePort (uint16_t port);
+ bool FreePort(uint16_t port);
- bool
- FreePortForProcess (lldb::pid_t pid);
+ bool FreePortForProcess(lldb::pid_t pid);
- void
- SetPortOffset (uint16_t port_offset);
+ void SetPortOffset(uint16_t port_offset);
- void
- SetInferiorArguments (const lldb_private::Args& args);
+ void SetInferiorArguments(const lldb_private::Args &args);
- Error
- LaunchGDBServer(const lldb_private::Args& args,
- std::string hostname,
- lldb::pid_t& pid,
- uint16_t& port,
- std::string& socket_name);
+ Error LaunchGDBServer(const lldb_private::Args &args, std::string hostname,
+ lldb::pid_t &pid, uint16_t &port,
+ std::string &socket_name);
- void
- SetPendingGdbServer(lldb::pid_t pid, uint16_t port, const std::string& socket_name);
+ void SetPendingGdbServer(lldb::pid_t pid, uint16_t port,
+ const std::string &socket_name);
protected:
- const Socket::SocketProtocol m_socket_protocol;
- const std::string m_socket_scheme;
- std::recursive_mutex m_spawned_pids_mutex;
- std::set<lldb::pid_t> m_spawned_pids;
+ const Socket::SocketProtocol m_socket_protocol;
+ const std::string m_socket_scheme;
+ std::recursive_mutex m_spawned_pids_mutex;
+ std::set<lldb::pid_t> m_spawned_pids;
- PortMap m_port_map;
- uint16_t m_port_offset;
- struct { lldb::pid_t pid; uint16_t port; std::string socket_name; } m_pending_gdb_server;
+ PortMap m_port_map;
+ uint16_t m_port_offset;
+ struct {
+ lldb::pid_t pid;
+ uint16_t port;
+ std::string socket_name;
+ } m_pending_gdb_server;
- PacketResult
- Handle_qLaunchGDBServer (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qLaunchGDBServer(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qQueryGDBServer (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qQueryGDBServer(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qKillSpawnedProcess (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qKillSpawnedProcess(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qProcessInfo (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qProcessInfo(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qGetWorkingDir (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qGetWorkingDir(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_QSetWorkingDir (StringExtractorGDBRemote &packet);
+ PacketResult Handle_QSetWorkingDir(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_qC (StringExtractorGDBRemote &packet);
+ PacketResult Handle_qC(StringExtractorGDBRemote &packet);
- PacketResult
- Handle_jSignalsInfo(StringExtractorGDBRemote &packet);
+ PacketResult Handle_jSignalsInfo(StringExtractorGDBRemote &packet);
private:
- bool
- KillSpawnedProcess (lldb::pid_t pid);
+ bool KillSpawnedProcess(lldb::pid_t pid);
- bool
- DebugserverProcessReaped (lldb::pid_t pid);
+ bool DebugserverProcessReaped(lldb::pid_t pid);
- static const FileSpec&
- GetDomainSocketDir();
+ static const FileSpec &GetDomainSocketDir();
- static FileSpec
- GetDomainSocketPath(const char* prefix);
+ static FileSpec GetDomainSocketPath(const char *prefix);
- DISALLOW_COPY_AND_ASSIGN (GDBRemoteCommunicationServerPlatform);
+ DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationServerPlatform);
};
} // namespace process_gdb_remote
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 57983c4..27ce67d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -21,12 +21,12 @@
#include "lldb/Target/Target.h"
#include "lldb/Utility/Utils.h"
// Project includes
-#include "Utility/StringExtractorGDBRemote.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
#include "Utility/ARM_DWARF_Registers.h"
#include "Utility/ARM_ehframe_Registers.h"
+#include "Utility/StringExtractorGDBRemote.h"
using namespace lldb;
using namespace lldb_private;
@@ -35,1189 +35,953 @@ using namespace lldb_private::process_gdb_remote;
//----------------------------------------------------------------------
// GDBRemoteRegisterContext constructor
//----------------------------------------------------------------------
-GDBRemoteRegisterContext::GDBRemoteRegisterContext
-(
- ThreadGDBRemote &thread,
- uint32_t concrete_frame_idx,
- GDBRemoteDynamicRegisterInfo &reg_info,
- bool read_all_at_once
-) :
- RegisterContext (thread, concrete_frame_idx),
- m_reg_info (reg_info),
- m_reg_valid (),
- m_reg_data (),
- m_read_all_at_once (read_all_at_once)
-{
- // Resize our vector of bools to contain one bool for every register.
- // We will use these boolean values to know when a register value
- // is valid in m_reg_data.
- m_reg_valid.resize (reg_info.GetNumRegisters());
-
- // Make a heap based buffer that is big enough to store all registers
- DataBufferSP reg_data_sp(new DataBufferHeap (reg_info.GetRegisterDataByteSize(), 0));
- m_reg_data.SetData (reg_data_sp);
- m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder());
+GDBRemoteRegisterContext::GDBRemoteRegisterContext(
+ ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
+ GDBRemoteDynamicRegisterInfo &reg_info, bool read_all_at_once)
+ : RegisterContext(thread, concrete_frame_idx), m_reg_info(reg_info),
+ m_reg_valid(), m_reg_data(), m_read_all_at_once(read_all_at_once) {
+ // Resize our vector of bools to contain one bool for every register.
+ // We will use these boolean values to know when a register value
+ // is valid in m_reg_data.
+ m_reg_valid.resize(reg_info.GetNumRegisters());
+
+ // Make a heap based buffer that is big enough to store all registers
+ DataBufferSP reg_data_sp(
+ new DataBufferHeap(reg_info.GetRegisterDataByteSize(), 0));
+ m_reg_data.SetData(reg_data_sp);
+ m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder());
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-GDBRemoteRegisterContext::~GDBRemoteRegisterContext()
-{
-}
+GDBRemoteRegisterContext::~GDBRemoteRegisterContext() {}
-void
-GDBRemoteRegisterContext::InvalidateAllRegisters ()
-{
- SetAllRegisterValid (false);
+void GDBRemoteRegisterContext::InvalidateAllRegisters() {
+ SetAllRegisterValid(false);
}
-void
-GDBRemoteRegisterContext::SetAllRegisterValid (bool b)
-{
- std::vector<bool>::iterator pos, end = m_reg_valid.end();
- for (pos = m_reg_valid.begin(); pos != end; ++pos)
- *pos = b;
+void GDBRemoteRegisterContext::SetAllRegisterValid(bool b) {
+ std::vector<bool>::iterator pos, end = m_reg_valid.end();
+ for (pos = m_reg_valid.begin(); pos != end; ++pos)
+ *pos = b;
}
-size_t
-GDBRemoteRegisterContext::GetRegisterCount ()
-{
- return m_reg_info.GetNumRegisters ();
+size_t GDBRemoteRegisterContext::GetRegisterCount() {
+ return m_reg_info.GetNumRegisters();
}
const RegisterInfo *
-GDBRemoteRegisterContext::GetRegisterInfoAtIndex (size_t reg)
-{
- RegisterInfo* reg_info = m_reg_info.GetRegisterInfoAtIndex (reg);
-
- if (reg_info && reg_info->dynamic_size_dwarf_expr_bytes)
- {
- const ArchSpec &arch = m_thread.GetProcess ()->GetTarget ().GetArchitecture ();
- uint8_t reg_size = UpdateDynamicRegisterSize (arch, reg_info);
- reg_info->byte_size = reg_size;
- }
- return reg_info;
+GDBRemoteRegisterContext::GetRegisterInfoAtIndex(size_t reg) {
+ RegisterInfo *reg_info = m_reg_info.GetRegisterInfoAtIndex(reg);
+
+ if (reg_info && reg_info->dynamic_size_dwarf_expr_bytes) {
+ const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture();
+ uint8_t reg_size = UpdateDynamicRegisterSize(arch, reg_info);
+ reg_info->byte_size = reg_size;
+ }
+ return reg_info;
}
-size_t
-GDBRemoteRegisterContext::GetRegisterSetCount ()
-{
- return m_reg_info.GetNumRegisterSets ();
+size_t GDBRemoteRegisterContext::GetRegisterSetCount() {
+ return m_reg_info.GetNumRegisterSets();
}
-
-
-const RegisterSet *
-GDBRemoteRegisterContext::GetRegisterSet (size_t reg_set)
-{
- return m_reg_info.GetRegisterSet (reg_set);
+const RegisterSet *GDBRemoteRegisterContext::GetRegisterSet(size_t reg_set) {
+ return m_reg_info.GetRegisterSet(reg_set);
}
+bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &value) {
+ // Read the register
+ if (ReadRegisterBytes(reg_info, m_reg_data)) {
+ const bool partial_data_ok = false;
+ Error error(value.SetValueFromData(reg_info, m_reg_data,
+ reg_info->byte_offset, partial_data_ok));
+ return error.Success();
+ }
+ return false;
+}
-
-bool
-GDBRemoteRegisterContext::ReadRegister (const RegisterInfo *reg_info, RegisterValue &value)
-{
- // Read the register
- if (ReadRegisterBytes (reg_info, m_reg_data))
- {
- const bool partial_data_ok = false;
- Error error (value.SetValueFromData(reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok));
- return error.Success();
- }
+bool GDBRemoteRegisterContext::PrivateSetRegisterValue(
+ uint32_t reg, llvm::ArrayRef<uint8_t> data) {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+ if (reg_info == NULL)
return false;
-}
-bool
-GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
-{
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
- if (reg_info == NULL)
- return false;
-
- // Invalidate if needed
- InvalidateIfNeeded(false);
-
- const uint32_t reg_byte_size = reg_info->byte_size;
- const size_t bytes_copied = response.GetHexBytes (const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)), reg_byte_size, '\xcc');
- bool success = bytes_copied == reg_byte_size;
- if (success)
- {
- SetRegisterIsValid(reg, true);
- }
- else if (bytes_copied > 0)
- {
- // Only set register is valid to false if we copied some bytes, else
- // leave it as it was.
- SetRegisterIsValid(reg, false);
- }
- return success;
+ // Invalidate if needed
+ InvalidateIfNeeded(false);
+
+ const size_t reg_byte_size = reg_info->byte_size;
+ memcpy(const_cast<uint8_t *>(
+ m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)),
+ data.data(), std::min(data.size(), reg_byte_size));
+ bool success = data.size() >= reg_byte_size;
+ if (success) {
+ SetRegisterIsValid(reg, true);
+ } else if (data.size() > 0) {
+ // Only set register is valid to false if we copied some bytes, else
+ // leave it as it was.
+ SetRegisterIsValid(reg, false);
+ }
+ return success;
}
-bool
-GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, uint64_t new_reg_val)
-{
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
- if (reg_info == NULL)
- return false;
-
- // Early in process startup, we can get a thread that has an invalid byte order
- // because the process hasn't been completely set up yet (see the ctor where the
- // byte order is setfrom the process). If that's the case, we can't set the
- // value here.
- if (m_reg_data.GetByteOrder() == eByteOrderInvalid)
- {
- return false;
- }
-
- // Invalidate if needed
- InvalidateIfNeeded (false);
+bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg,
+ uint64_t new_reg_val) {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+ if (reg_info == NULL)
+ return false;
- DataBufferSP buffer_sp (new DataBufferHeap (&new_reg_val, sizeof (new_reg_val)));
- DataExtractor data (buffer_sp, endian::InlHostByteOrder(), sizeof (void*));
+ // Early in process startup, we can get a thread that has an invalid byte
+ // order
+ // because the process hasn't been completely set up yet (see the ctor where
+ // the
+ // byte order is setfrom the process). If that's the case, we can't set the
+ // value here.
+ if (m_reg_data.GetByteOrder() == eByteOrderInvalid) {
+ return false;
+ }
- // If our register context and our register info disagree, which should never happen, don't
- // overwrite past the end of the buffer.
- if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
- return false;
+ // Invalidate if needed
+ InvalidateIfNeeded(false);
- // Grab a pointer to where we are going to put this register
- uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
+ DataBufferSP buffer_sp(new DataBufferHeap(&new_reg_val, sizeof(new_reg_val)));
+ DataExtractor data(buffer_sp, endian::InlHostByteOrder(), sizeof(void *));
- if (dst == NULL)
- return false;
+ // If our register context and our register info disagree, which should never
+ // happen, don't
+ // overwrite past the end of the buffer.
+ if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
+ return false;
+ // Grab a pointer to where we are going to put this register
+ uint8_t *dst = const_cast<uint8_t *>(
+ m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
- if (data.CopyByteOrderedData (0, // src offset
- reg_info->byte_size, // src length
- dst, // dst
- reg_info->byte_size, // dst length
- m_reg_data.GetByteOrder())) // dst byte order
- {
- SetRegisterIsValid (reg, true);
- return true;
- }
+ if (dst == NULL)
return false;
+
+ if (data.CopyByteOrderedData(0, // src offset
+ reg_info->byte_size, // src length
+ dst, // dst
+ reg_info->byte_size, // dst length
+ m_reg_data.GetByteOrder())) // dst byte order
+ {
+ SetRegisterIsValid(reg, true);
+ return true;
+ }
+ return false;
}
// Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().
-bool
-GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info,
- GDBRemoteCommunicationClient &gdb_comm)
-{
- const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB];
- const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin];
- StringExtractorGDBRemote response;
- if (gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg, response))
- return PrivateSetRegisterValue (lldb_reg, response);
- return false;
+bool GDBRemoteRegisterContext::GetPrimordialRegister(
+ const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) {
+ const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB];
+ const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin];
+ StringExtractorGDBRemote response;
+ if (DataBufferSP buffer_sp =
+ gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg))
+ return PrivateSetRegisterValue(
+ lldb_reg, llvm::ArrayRef<uint8_t>(buffer_sp->GetBytes(),
+ buffer_sp->GetByteSize()));
+ return false;
}
-bool
-GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataExtractor &data)
-{
- ExecutionContext exe_ctx (CalculateThread());
+bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info,
+ DataExtractor &data) {
+ ExecutionContext exe_ctx(CalculateThread());
- Process *process = exe_ctx.GetProcessPtr();
- Thread *thread = exe_ctx.GetThreadPtr();
- if (process == NULL || thread == NULL)
- return false;
-
- GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (process == NULL || thread == NULL)
+ return false;
- InvalidateIfNeeded(false);
+ GDBRemoteCommunicationClient &gdb_comm(
+ ((ProcessGDBRemote *)process)->GetGDBRemote());
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ InvalidateIfNeeded(false);
- if (!GetRegisterIsValid(reg))
- {
- if (m_read_all_at_once)
- {
- StringExtractorGDBRemote response;
- if (!gdb_comm.ReadAllRegisters(m_thread.GetProtocolID(), response))
- return false;
- if (response.IsNormalResponse())
- if (response.GetHexBytes(const_cast<void *>(reinterpret_cast<const void *>(m_reg_data.GetDataStart())),
- m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
- SetAllRegisterValid (true);
- }
- else if (reg_info->value_regs)
- {
- // Process this composite register request by delegating to the constituent
- // primordial registers.
-
- // Index of the primordial register.
- bool success = true;
- for (uint32_t idx = 0; success; ++idx)
- {
- const uint32_t prim_reg = reg_info->value_regs[idx];
- if (prim_reg == LLDB_INVALID_REGNUM)
- break;
- // We have a valid primordial register as our constituent.
- // Grab the corresponding register info.
- const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
- if (prim_reg_info == NULL)
- success = false;
- else
- {
- // Read the containing register if it hasn't already been read
- if (!GetRegisterIsValid(prim_reg))
- success = GetPrimordialRegister(prim_reg_info, gdb_comm);
- }
- }
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- if (success)
- {
- // If we reach this point, all primordial register requests have succeeded.
- // Validate this composite register.
- SetRegisterIsValid (reg_info, true);
- }
+ if (!GetRegisterIsValid(reg)) {
+ if (m_read_all_at_once) {
+ if (DataBufferSP buffer_sp =
+ gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) {
+ memcpy(const_cast<uint8_t *>(m_reg_data.GetDataStart()),
+ buffer_sp->GetBytes(),
+ std::min(buffer_sp->GetByteSize(), m_reg_data.GetByteSize()));
+ if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize()) {
+ SetAllRegisterValid(true);
+ return true;
}
- else
- {
- // Get each register individually
- GetPrimordialRegister(reg_info, gdb_comm);
+ }
+ return false;
+ }
+ if (reg_info->value_regs) {
+ // Process this composite register request by delegating to the
+ // constituent
+ // primordial registers.
+
+ // Index of the primordial register.
+ bool success = true;
+ for (uint32_t idx = 0; success; ++idx) {
+ const uint32_t prim_reg = reg_info->value_regs[idx];
+ if (prim_reg == LLDB_INVALID_REGNUM)
+ break;
+ // We have a valid primordial register as our constituent.
+ // Grab the corresponding register info.
+ const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg);
+ if (prim_reg_info == NULL)
+ success = false;
+ else {
+ // Read the containing register if it hasn't already been read
+ if (!GetRegisterIsValid(prim_reg))
+ success = GetPrimordialRegister(prim_reg_info, gdb_comm);
}
-
- // Make sure we got a valid register value after reading it
- if (!GetRegisterIsValid(reg))
- return false;
+ }
+
+ if (success) {
+ // If we reach this point, all primordial register requests have
+ // succeeded.
+ // Validate this composite register.
+ SetRegisterIsValid(reg_info, true);
+ }
+ } else {
+ // Get each register individually
+ GetPrimordialRegister(reg_info, gdb_comm);
}
- if (&data != &m_reg_data)
- {
-#if defined (LLDB_CONFIGURATION_DEBUG)
- assert (m_reg_data.GetByteSize() >= reg_info->byte_offset + reg_info->byte_size);
-#endif
- // If our register context and our register info disagree, which should never happen, don't
- // read past the end of the buffer.
- if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
- return false;
-
- // If we aren't extracting into our own buffer (which
- // only happens when this function is called from
- // ReadRegisterValue(uint32_t, Scalar&)) then
- // we transfer bytes from our buffer into the data
- // buffer that was passed in
-
- data.SetByteOrder (m_reg_data.GetByteOrder());
- data.SetData (m_reg_data, reg_info->byte_offset, reg_info->byte_size);
- }
- return true;
-}
+ // Make sure we got a valid register value after reading it
+ if (!GetRegisterIsValid(reg))
+ return false;
+ }
-bool
-GDBRemoteRegisterContext::WriteRegister (const RegisterInfo *reg_info,
- const RegisterValue &value)
-{
- DataExtractor data;
- if (value.GetData (data))
- return WriteRegisterBytes (reg_info, data, 0);
- return false;
+ if (&data != &m_reg_data) {
+#if defined(LLDB_CONFIGURATION_DEBUG)
+ assert(m_reg_data.GetByteSize() >=
+ reg_info->byte_offset + reg_info->byte_size);
+#endif
+ // If our register context and our register info disagree, which should
+ // never happen, don't
+ // read past the end of the buffer.
+ if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
+ return false;
+
+ // If we aren't extracting into our own buffer (which
+ // only happens when this function is called from
+ // ReadRegisterValue(uint32_t, Scalar&)) then
+ // we transfer bytes from our buffer into the data
+ // buffer that was passed in
+
+ data.SetByteOrder(m_reg_data.GetByteOrder());
+ data.SetData(m_reg_data, reg_info->byte_offset, reg_info->byte_size);
+ }
+ return true;
}
-// Helper function for GDBRemoteRegisterContext::WriteRegisterBytes().
-bool
-GDBRemoteRegisterContext::SetPrimordialRegister(const RegisterInfo *reg_info,
- GDBRemoteCommunicationClient &gdb_comm)
-{
- StreamString packet;
- StringExtractorGDBRemote response;
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
- packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]);
- packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
- reg_info->byte_size,
- endian::InlHostByteOrder(),
- endian::InlHostByteOrder());
-
- if (gdb_comm.GetThreadSuffixSupported())
- packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
-
- // Invalidate just this register
- SetRegisterIsValid(reg, false);
- if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
- packet.GetString().size(),
- response,
- false) == GDBRemoteCommunication::PacketResult::Success)
- {
- if (response.IsOKResponse())
- return true;
- }
- return false;
+bool GDBRemoteRegisterContext::WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &value) {
+ DataExtractor data;
+ if (value.GetData(data))
+ return WriteRegisterBytes(reg_info, data, 0);
+ return false;
}
-void
-GDBRemoteRegisterContext::SyncThreadState(Process *process)
-{
- // NB. We assume our caller has locked the sequence mutex.
-
- GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *) process)->GetGDBRemote());
- if (!gdb_comm.GetSyncThreadStateSupported())
- return;
-
- StreamString packet;
- StringExtractorGDBRemote response;
- packet.Printf ("QSyncThreadState:%4.4" PRIx64 ";", m_thread.GetProtocolID());
- if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
- packet.GetString().size(),
- response,
- false) == GDBRemoteCommunication::PacketResult::Success)
- {
- if (response.IsOKResponse())
- InvalidateAllRegisters();
- }
+// Helper function for GDBRemoteRegisterContext::WriteRegisterBytes().
+bool GDBRemoteRegisterContext::SetPrimordialRegister(
+ const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) {
+ StreamString packet;
+ StringExtractorGDBRemote response;
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ // Invalidate just this register
+ SetRegisterIsValid(reg, false);
+
+ return gdb_comm.WriteRegister(
+ m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin],
+ {m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
+ reg_info->byte_size});
}
-bool
-GDBRemoteRegisterContext::WriteRegisterBytes (const RegisterInfo *reg_info, DataExtractor &data, uint32_t data_offset)
-{
- ExecutionContext exe_ctx (CalculateThread());
+bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
+ DataExtractor &data,
+ uint32_t data_offset) {
+ ExecutionContext exe_ctx(CalculateThread());
- Process *process = exe_ctx.GetProcessPtr();
- Thread *thread = exe_ctx.GetThreadPtr();
- if (process == NULL || thread == NULL)
- return false;
-
- GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
-// FIXME: This check isn't right because IsRunning checks the Public state, but this
-// is work you need to do - for instance in ShouldStop & friends - before the public
-// state has been changed.
-// if (gdb_comm.IsRunning())
-// return false;
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (process == NULL || thread == NULL)
+ return false;
+ GDBRemoteCommunicationClient &gdb_comm(
+ ((ProcessGDBRemote *)process)->GetGDBRemote());
-#if defined (LLDB_CONFIGURATION_DEBUG)
- assert (m_reg_data.GetByteSize() >= reg_info->byte_offset + reg_info->byte_size);
+#if defined(LLDB_CONFIGURATION_DEBUG)
+ assert(m_reg_data.GetByteSize() >=
+ reg_info->byte_offset + reg_info->byte_size);
#endif
- // If our register context and our register info disagree, which should never happen, don't
- // overwrite past the end of the buffer.
- if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
- return false;
+ // If our register context and our register info disagree, which should never
+ // happen, don't
+ // overwrite past the end of the buffer.
+ if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
+ return false;
- // Grab a pointer to where we are going to put this register
- uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
+ // Grab a pointer to where we are going to put this register
+ uint8_t *dst = const_cast<uint8_t *>(
+ m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
- if (dst == NULL)
- return false;
+ if (dst == NULL)
+ return false;
+ if (data.CopyByteOrderedData(data_offset, // src offset
+ reg_info->byte_size, // src length
+ dst, // dst
+ reg_info->byte_size, // dst length
+ m_reg_data.GetByteOrder())) // dst byte order
+ {
+ GDBRemoteClientBase::Lock lock(gdb_comm, false);
+ if (lock) {
+ if (m_read_all_at_once) {
+ // Invalidate all register values
+ InvalidateIfNeeded(true);
+
+ // Set all registers in one packet
+ if (gdb_comm.WriteAllRegisters(
+ m_thread.GetProtocolID(),
+ {m_reg_data.GetDataStart(), size_t(m_reg_data.GetByteSize())}))
- if (data.CopyByteOrderedData (data_offset, // src offset
- reg_info->byte_size, // src length
- dst, // dst
- reg_info->byte_size, // dst length
- m_reg_data.GetByteOrder())) // dst byte order
- {
- Mutex::Locker locker;
- if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for write register."))
{
- const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
- ProcessSP process_sp (m_thread.GetProcess());
- if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
- {
- StreamString packet;
- StringExtractorGDBRemote response;
-
- if (m_read_all_at_once)
- {
- // Set all registers in one packet
- packet.PutChar ('G');
- packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),
- m_reg_data.GetByteSize(),
- endian::InlHostByteOrder(),
- endian::InlHostByteOrder());
-
- if (thread_suffix_supported)
- packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
-
- // Invalidate all register values
- InvalidateIfNeeded (true);
-
- if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
- packet.GetString().size(),
- response,
- false) == GDBRemoteCommunication::PacketResult::Success)
- {
- SetAllRegisterValid (false);
- if (response.IsOKResponse())
- {
- return true;
- }
- }
- }
- else
- {
- bool success = true;
-
- if (reg_info->value_regs)
- {
- // This register is part of another register. In this case we read the actual
- // register data for any "value_regs", and once all that data is read, we will
- // have enough data in our register context bytes for the value of this register
-
- // Invalidate this composite register first.
-
- for (uint32_t idx = 0; success; ++idx)
- {
- const uint32_t reg = reg_info->value_regs[idx];
- if (reg == LLDB_INVALID_REGNUM)
- break;
- // We have a valid primordial register as our constituent.
- // Grab the corresponding register info.
- const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
- if (value_reg_info == NULL)
- success = false;
- else
- success = SetPrimordialRegister(value_reg_info, gdb_comm);
- }
- }
- else
- {
- // This is an actual register, write it
- success = SetPrimordialRegister(reg_info, gdb_comm);
- }
-
- // Check if writing this register will invalidate any other register values?
- // If so, invalidate them
- if (reg_info->invalidate_regs)
- {
- for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
- reg != LLDB_INVALID_REGNUM;
- reg = reg_info->invalidate_regs[++idx])
- {
- SetRegisterIsValid(reg, false);
- }
- }
-
- return success;
- }
- }
+ SetAllRegisterValid(false);
+ return true;
}
- else
- {
- Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
- if (log)
- {
- if (log->GetVerbose())
- {
- StreamString strm;
- gdb_comm.DumpHistory(strm);
- log->Printf("error: failed to get packet sequence mutex, not sending write register for \"%s\":\n%s", reg_info->name, strm.GetData());
- }
- else
- log->Printf("error: failed to get packet sequence mutex, not sending write register for \"%s\"", reg_info->name);
- }
+ } else {
+ bool success = true;
+
+ if (reg_info->value_regs) {
+ // This register is part of another register. In this case we read the
+ // actual
+ // register data for any "value_regs", and once all that data is read,
+ // we will
+ // have enough data in our register context bytes for the value of
+ // this register
+
+ // Invalidate this composite register first.
+
+ for (uint32_t idx = 0; success; ++idx) {
+ const uint32_t reg = reg_info->value_regs[idx];
+ if (reg == LLDB_INVALID_REGNUM)
+ break;
+ // We have a valid primordial register as our constituent.
+ // Grab the corresponding register info.
+ const RegisterInfo *value_reg_info = GetRegisterInfoAtIndex(reg);
+ if (value_reg_info == NULL)
+ success = false;
+ else
+ success = SetPrimordialRegister(value_reg_info, gdb_comm);
+ }
+ } else {
+ // This is an actual register, write it
+ success = SetPrimordialRegister(reg_info, gdb_comm);
+ }
+
+ // Check if writing this register will invalidate any other register
+ // values?
+ // If so, invalidate them
+ if (reg_info->invalidate_regs) {
+ for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
+ reg != LLDB_INVALID_REGNUM;
+ reg = reg_info->invalidate_regs[++idx]) {
+ SetRegisterIsValid(reg, false);
+ }
}
+
+ return success;
+ }
+ } else {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD |
+ GDBR_LOG_PACKETS));
+ if (log) {
+ if (log->GetVerbose()) {
+ StreamString strm;
+ gdb_comm.DumpHistory(strm);
+ log->Printf("error: failed to get packet sequence mutex, not sending "
+ "write register for \"%s\":\n%s",
+ reg_info->name, strm.GetData());
+ } else
+ log->Printf("error: failed to get packet sequence mutex, not sending "
+ "write register for \"%s\"",
+ reg_info->name);
+ }
}
+ }
+ return false;
+}
+
+bool GDBRemoteRegisterContext::ReadAllRegisterValues(
+ RegisterCheckpoint &reg_checkpoint) {
+ ExecutionContext exe_ctx(CalculateThread());
+
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (process == NULL || thread == NULL)
return false;
+
+ GDBRemoteCommunicationClient &gdb_comm(
+ ((ProcessGDBRemote *)process)->GetGDBRemote());
+
+ uint32_t save_id = 0;
+ if (gdb_comm.SaveRegisterState(thread->GetProtocolID(), save_id)) {
+ reg_checkpoint.SetID(save_id);
+ reg_checkpoint.GetData().reset();
+ return true;
+ } else {
+ reg_checkpoint.SetID(0); // Invalid save ID is zero
+ return ReadAllRegisterValues(reg_checkpoint.GetData());
+ }
}
-bool
-GDBRemoteRegisterContext::ReadAllRegisterValues (RegisterCheckpoint &reg_checkpoint)
-{
- ExecutionContext exe_ctx (CalculateThread());
-
+bool GDBRemoteRegisterContext::WriteAllRegisterValues(
+ const RegisterCheckpoint &reg_checkpoint) {
+ uint32_t save_id = reg_checkpoint.GetID();
+ if (save_id != 0) {
+ ExecutionContext exe_ctx(CalculateThread());
+
Process *process = exe_ctx.GetProcessPtr();
Thread *thread = exe_ctx.GetThreadPtr();
if (process == NULL || thread == NULL)
- return false;
-
- GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
-
- uint32_t save_id = 0;
- if (gdb_comm.SaveRegisterState(thread->GetProtocolID(), save_id))
- {
- reg_checkpoint.SetID(save_id);
- reg_checkpoint.GetData().reset();
- return true;
- }
- else
- {
- reg_checkpoint.SetID(0); // Invalid save ID is zero
- return ReadAllRegisterValues(reg_checkpoint.GetData());
- }
-}
+ return false;
-bool
-GDBRemoteRegisterContext::WriteAllRegisterValues (const RegisterCheckpoint &reg_checkpoint)
-{
- uint32_t save_id = reg_checkpoint.GetID();
- if (save_id != 0)
- {
- ExecutionContext exe_ctx (CalculateThread());
-
- Process *process = exe_ctx.GetProcessPtr();
- Thread *thread = exe_ctx.GetThreadPtr();
- if (process == NULL || thread == NULL)
- return false;
-
- GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
-
- return gdb_comm.RestoreRegisterState(m_thread.GetProtocolID(), save_id);
- }
- else
- {
- return WriteAllRegisterValues(reg_checkpoint.GetData());
- }
+ GDBRemoteCommunicationClient &gdb_comm(
+ ((ProcessGDBRemote *)process)->GetGDBRemote());
+
+ return gdb_comm.RestoreRegisterState(m_thread.GetProtocolID(), save_id);
+ } else {
+ return WriteAllRegisterValues(reg_checkpoint.GetData());
+ }
}
-bool
-GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
-{
- ExecutionContext exe_ctx (CalculateThread());
+bool GDBRemoteRegisterContext::ReadAllRegisterValues(
+ lldb::DataBufferSP &data_sp) {
+ ExecutionContext exe_ctx(CalculateThread());
- Process *process = exe_ctx.GetProcessPtr();
- Thread *thread = exe_ctx.GetThreadPtr();
- if (process == NULL || thread == NULL)
- return false;
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (process == NULL || thread == NULL)
+ return false;
- GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
+ GDBRemoteCommunicationClient &gdb_comm(
+ ((ProcessGDBRemote *)process)->GetGDBRemote());
- StringExtractorGDBRemote response;
+ const bool use_g_packet =
+ gdb_comm.AvoidGPackets((ProcessGDBRemote *)process) == false;
- const bool use_g_packet = gdb_comm.AvoidGPackets ((ProcessGDBRemote *)process) == false;
+ GDBRemoteClientBase::Lock lock(gdb_comm, false);
+ if (lock) {
+ if (gdb_comm.SyncThreadState(m_thread.GetProtocolID()))
+ InvalidateAllRegisters();
- Mutex::Locker locker;
- if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for read all registers."))
- {
- SyncThreadState(process);
-
- char packet[32];
- const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
- ProcessSP process_sp (m_thread.GetProcess());
- if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
- {
- int packet_len = 0;
- if (thread_suffix_supported)
- packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64, m_thread.GetProtocolID());
- else
- packet_len = ::snprintf (packet, sizeof(packet), "g");
- assert (packet_len < ((int)sizeof(packet) - 1));
-
- if (use_g_packet && gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
- {
- int packet_len = 0;
- if (thread_suffix_supported)
- packet_len = ::snprintf (packet, sizeof(packet), "g;thread:%4.4" PRIx64, m_thread.GetProtocolID());
- else
- packet_len = ::snprintf (packet, sizeof(packet), "g");
- assert (packet_len < ((int)sizeof(packet) - 1));
-
- if (gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
- {
- if (response.IsErrorResponse())
- return false;
-
- std::string &response_str = response.GetStringRef();
- if (isxdigit(response_str[0]))
- {
- response_str.insert(0, 1, 'G');
- if (thread_suffix_supported)
- {
- char thread_id_cstr[64];
- ::snprintf (thread_id_cstr, sizeof(thread_id_cstr), ";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
- response_str.append (thread_id_cstr);
- }
- data_sp.reset (new DataBufferHeap (response_str.c_str(), response_str.size()));
- return true;
- }
- }
- }
- else
- {
- // For the use_g_packet == false case, we're going to read each register
- // individually and store them as binary data in a buffer instead of as ascii
- // characters.
- const RegisterInfo *reg_info;
-
- // data_sp will take ownership of this DataBufferHeap pointer soon.
- DataBufferSP reg_ctx(new DataBufferHeap(m_reg_info.GetRegisterDataByteSize(), 0));
-
- for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex (i)) != NULL; i++)
- {
- if (reg_info->value_regs) // skip registers that are slices of real registers
- continue;
- ReadRegisterBytes (reg_info, m_reg_data);
- // ReadRegisterBytes saves the contents of the register in to the m_reg_data buffer
- }
- memcpy (reg_ctx->GetBytes(), m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize());
-
- data_sp = reg_ctx;
- return true;
- }
- }
- }
- else
- {
+ if (use_g_packet &&
+ (data_sp = gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())))
+ return true;
- Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
- if (log)
- {
- if (log->GetVerbose())
- {
- StreamString strm;
- gdb_comm.DumpHistory(strm);
- log->Printf("error: failed to get packet sequence mutex, not sending read all registers:\n%s", strm.GetData());
- }
- else
- log->Printf("error: failed to get packet sequence mutex, not sending read all registers");
- }
+ // We're going to read each register
+ // individually and store them as binary data in a buffer.
+ const RegisterInfo *reg_info;
+
+ for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; i++) {
+ if (reg_info
+ ->value_regs) // skip registers that are slices of real registers
+ continue;
+ ReadRegisterBytes(reg_info, m_reg_data);
+ // ReadRegisterBytes saves the contents of the register in to the
+ // m_reg_data buffer
}
+ data_sp.reset(new DataBufferHeap(m_reg_data.GetDataStart(),
+ m_reg_info.GetRegisterDataByteSize()));
+ return true;
+ } else {
+
+ Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD |
+ GDBR_LOG_PACKETS));
+ if (log) {
+ if (log->GetVerbose()) {
+ StreamString strm;
+ gdb_comm.DumpHistory(strm);
+ log->Printf("error: failed to get packet sequence mutex, not sending "
+ "read all registers:\n%s",
+ strm.GetData());
+ } else
+ log->Printf("error: failed to get packet sequence mutex, not sending "
+ "read all registers");
+ }
+ }
- data_sp.reset();
- return false;
+ data_sp.reset();
+ return false;
}
-bool
-GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data_sp)
-{
- if (!data_sp || data_sp->GetBytes() == NULL || data_sp->GetByteSize() == 0)
- return false;
+bool GDBRemoteRegisterContext::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ if (!data_sp || data_sp->GetBytes() == NULL || data_sp->GetByteSize() == 0)
+ return false;
- ExecutionContext exe_ctx (CalculateThread());
+ ExecutionContext exe_ctx(CalculateThread());
- Process *process = exe_ctx.GetProcessPtr();
- Thread *thread = exe_ctx.GetThreadPtr();
- if (process == NULL || thread == NULL)
- return false;
+ Process *process = exe_ctx.GetProcessPtr();
+ Thread *thread = exe_ctx.GetThreadPtr();
+ if (process == NULL || thread == NULL)
+ return false;
- GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
+ GDBRemoteCommunicationClient &gdb_comm(
+ ((ProcessGDBRemote *)process)->GetGDBRemote());
- const bool use_g_packet = gdb_comm.AvoidGPackets ((ProcessGDBRemote *)process) == false;
+ const bool use_g_packet =
+ gdb_comm.AvoidGPackets((ProcessGDBRemote *)process) == false;
- StringExtractorGDBRemote response;
- Mutex::Locker locker;
- if (gdb_comm.GetSequenceMutex (locker, "Didn't get sequence mutex for write all registers."))
- {
- const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
- ProcessSP process_sp (m_thread.GetProcess());
- if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
- {
- // The data_sp contains the entire G response packet including the
- // G, and if the thread suffix is supported, it has the thread suffix
- // as well.
- const char *G_packet = (const char *)data_sp->GetBytes();
- size_t G_packet_len = data_sp->GetByteSize();
- if (use_g_packet
- && gdb_comm.SendPacketAndWaitForResponse (G_packet,
- G_packet_len,
- response,
- false) == GDBRemoteCommunication::PacketResult::Success)
- {
- // The data_sp contains the entire G response packet including the
- // G, and if the thread suffix is supported, it has the thread suffix
- // as well.
- const char *G_packet = (const char *)data_sp->GetBytes();
- size_t G_packet_len = data_sp->GetByteSize();
- if (gdb_comm.SendPacketAndWaitForResponse (G_packet,
- G_packet_len,
- response,
- false) == GDBRemoteCommunication::PacketResult::Success)
- {
- if (response.IsOKResponse())
- return true;
- else if (response.IsErrorResponse())
- {
- uint32_t num_restored = 0;
- // We need to manually go through all of the registers and
- // restore them manually
-
- response.GetStringRef().assign (G_packet, G_packet_len);
- response.SetFilePos(1); // Skip the leading 'G'
-
- // G_packet_len is hex-ascii characters plus prefix 'G' plus suffix thread specifier.
- // This means buffer will be a little more than 2x larger than necessary but we resize
- // it down once we've extracted all hex ascii chars from the packet.
- DataBufferHeap buffer (G_packet_len, 0);
-
- const uint32_t bytes_extracted = response.GetHexBytes (buffer.GetBytes(),
- buffer.GetByteSize(),
- '\xcc');
-
- DataExtractor restore_data (buffer.GetBytes(),
- buffer.GetByteSize(),
- m_reg_data.GetByteOrder(),
- m_reg_data.GetAddressByteSize());
-
- if (bytes_extracted < restore_data.GetByteSize())
- restore_data.SetData(restore_data.GetDataStart(), bytes_extracted, m_reg_data.GetByteOrder());
-
- const RegisterInfo *reg_info;
-
- // The g packet contents may either include the slice registers (registers defined in
- // terms of other registers, e.g. eax is a subset of rax) or not. The slice registers
- // should NOT be in the g packet, but some implementations may incorrectly include them.
- //
- // If the slice registers are included in the packet, we must step over the slice registers
- // when parsing the packet -- relying on the RegisterInfo byte_offset field would be incorrect.
- // If the slice registers are not included, then using the byte_offset values into the
- // data buffer is the best way to find individual register values.
-
- uint64_t size_including_slice_registers = 0;
- uint64_t size_not_including_slice_registers = 0;
- uint64_t size_by_highest_offset = 0;
-
- for (uint32_t reg_idx=0; (reg_info = GetRegisterInfoAtIndex (reg_idx)) != NULL; ++reg_idx)
- {
- size_including_slice_registers += reg_info->byte_size;
- if (reg_info->value_regs == NULL)
- size_not_including_slice_registers += reg_info->byte_size;
- if (reg_info->byte_offset >= size_by_highest_offset)
- size_by_highest_offset = reg_info->byte_offset + reg_info->byte_size;
- }
-
- bool use_byte_offset_into_buffer;
- if (size_by_highest_offset == restore_data.GetByteSize())
- {
- // The size of the packet agrees with the highest offset: + size in the register file
- use_byte_offset_into_buffer = true;
- }
- else if (size_not_including_slice_registers == restore_data.GetByteSize())
- {
- // The size of the packet is the same as concatenating all of the registers sequentially,
- // skipping the slice registers
- use_byte_offset_into_buffer = true;
- }
- else if (size_including_slice_registers == restore_data.GetByteSize())
- {
- // The slice registers are present in the packet (when they shouldn't be).
- // Don't try to use the RegisterInfo byte_offset into the restore_data, it will
- // point to the wrong place.
- use_byte_offset_into_buffer = false;
- }
- else {
- // None of our expected sizes match the actual g packet data we're looking at.
- // The most conservative approach here is to use the running total byte offset.
- use_byte_offset_into_buffer = false;
- }
-
- // In case our register definitions don't include the correct offsets,
- // keep track of the size of each reg & compute offset based on that.
- uint32_t running_byte_offset = 0;
- for (uint32_t reg_idx=0; (reg_info = GetRegisterInfoAtIndex (reg_idx)) != NULL; ++reg_idx, running_byte_offset += reg_info->byte_size)
- {
- // Skip composite aka slice registers (e.g. eax is a slice of rax).
- if (reg_info->value_regs)
- continue;
-
- const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
- uint32_t register_offset;
- if (use_byte_offset_into_buffer)
- {
- register_offset = reg_info->byte_offset;
- }
- else
- {
- register_offset = running_byte_offset;
- }
-
- // Only write down the registers that need to be written
- // if we are going to be doing registers individually.
- bool write_reg = true;
- const uint32_t reg_byte_size = reg_info->byte_size;
-
- const char *restore_src = (const char *)restore_data.PeekData(register_offset, reg_byte_size);
- if (restore_src)
- {
- StreamString packet;
- packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]);
- packet.PutBytesAsRawHex8 (restore_src,
- reg_byte_size,
- endian::InlHostByteOrder(),
- endian::InlHostByteOrder());
-
- if (thread_suffix_supported)
- packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
-
- SetRegisterIsValid(reg, false);
- if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
- packet.GetString().size(),
- response,
- false) == GDBRemoteCommunication::PacketResult::Success)
- {
- const char *current_src = (const char *)m_reg_data.PeekData(register_offset, reg_byte_size);
- if (current_src)
- write_reg = memcmp (current_src, restore_src, reg_byte_size) != 0;
- }
-
- if (write_reg)
- {
- StreamString packet;
- packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]);
- packet.PutBytesAsRawHex8 (restore_src,
- reg_byte_size,
- endian::InlHostByteOrder(),
- endian::InlHostByteOrder());
-
- if (thread_suffix_supported)
- packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
-
- SetRegisterIsValid(reg, false);
- if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
- packet.GetString().size(),
- response,
- false) == GDBRemoteCommunication::PacketResult::Success)
- {
- if (response.IsOKResponse())
- ++num_restored;
- }
- }
- }
- }
- return num_restored > 0;
- }
- }
- }
- else
- {
- // For the use_g_packet == false case, we're going to write each register
- // individually. The data buffer is binary data in this case, instead of
- // ascii characters.
-
- bool arm64_debugserver = false;
- if (m_thread.GetProcess().get())
- {
- const ArchSpec &arch = m_thread.GetProcess()->GetTarget().GetArchitecture();
- if (arch.IsValid()
- && arch.GetMachine() == llvm::Triple::aarch64
- && arch.GetTriple().getVendor() == llvm::Triple::Apple
- && arch.GetTriple().getOS() == llvm::Triple::IOS)
- {
- arm64_debugserver = true;
- }
- }
- uint32_t num_restored = 0;
- const RegisterInfo *reg_info;
- for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex (i)) != NULL; i++)
- {
- if (reg_info->value_regs) // skip registers that are slices of real registers
- continue;
- // Skip the fpsr and fpcr floating point status/control register writing to
- // work around a bug in an older version of debugserver that would lead to
- // register context corruption when writing fpsr/fpcr.
- if (arm64_debugserver &&
- (strcmp (reg_info->name, "fpsr") == 0 || strcmp (reg_info->name, "fpcr") == 0))
- {
- continue;
- }
- StreamString packet;
- packet.Printf ("P%x=", reg_info->kinds[eRegisterKindProcessPlugin]);
- packet.PutBytesAsRawHex8 (data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size, endian::InlHostByteOrder(), endian::InlHostByteOrder());
- if (thread_suffix_supported)
- packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
-
- SetRegisterIsValid(reg_info, false);
- if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
- packet.GetString().size(),
- response,
- false) == GDBRemoteCommunication::PacketResult::Success)
- {
- if (response.IsOKResponse())
- ++num_restored;
- }
- }
- return num_restored > 0;
- }
+ GDBRemoteClientBase::Lock lock(gdb_comm, false);
+ if (lock) {
+ // The data_sp contains the G response packet.
+ if (use_g_packet) {
+ if (gdb_comm.WriteAllRegisters(
+ m_thread.GetProtocolID(),
+ {data_sp->GetBytes(), size_t(data_sp->GetByteSize())}))
+ return true;
+
+ uint32_t num_restored = 0;
+ // We need to manually go through all of the registers and
+ // restore them manually
+ DataExtractor restore_data(data_sp, m_reg_data.GetByteOrder(),
+ m_reg_data.GetAddressByteSize());
+
+ const RegisterInfo *reg_info;
+
+ // The g packet contents may either include the slice registers (registers
+ // defined in
+ // terms of other registers, e.g. eax is a subset of rax) or not. The
+ // slice registers
+ // should NOT be in the g packet, but some implementations may incorrectly
+ // include them.
+ //
+ // If the slice registers are included in the packet, we must step over
+ // the slice registers
+ // when parsing the packet -- relying on the RegisterInfo byte_offset
+ // field would be incorrect.
+ // If the slice registers are not included, then using the byte_offset
+ // values into the
+ // data buffer is the best way to find individual register values.
+
+ uint64_t size_including_slice_registers = 0;
+ uint64_t size_not_including_slice_registers = 0;
+ uint64_t size_by_highest_offset = 0;
+
+ for (uint32_t reg_idx = 0;
+ (reg_info = GetRegisterInfoAtIndex(reg_idx)) != NULL; ++reg_idx) {
+ size_including_slice_registers += reg_info->byte_size;
+ if (reg_info->value_regs == NULL)
+ size_not_including_slice_registers += reg_info->byte_size;
+ if (reg_info->byte_offset >= size_by_highest_offset)
+ size_by_highest_offset = reg_info->byte_offset + reg_info->byte_size;
+ }
+
+ bool use_byte_offset_into_buffer;
+ if (size_by_highest_offset == restore_data.GetByteSize()) {
+ // The size of the packet agrees with the highest offset: + size in the
+ // register file
+ use_byte_offset_into_buffer = true;
+ } else if (size_not_including_slice_registers ==
+ restore_data.GetByteSize()) {
+ // The size of the packet is the same as concatenating all of the
+ // registers sequentially,
+ // skipping the slice registers
+ use_byte_offset_into_buffer = true;
+ } else if (size_including_slice_registers == restore_data.GetByteSize()) {
+ // The slice registers are present in the packet (when they shouldn't
+ // be).
+ // Don't try to use the RegisterInfo byte_offset into the restore_data,
+ // it will
+ // point to the wrong place.
+ use_byte_offset_into_buffer = false;
+ } else {
+ // None of our expected sizes match the actual g packet data we're
+ // looking at.
+ // The most conservative approach here is to use the running total byte
+ // offset.
+ use_byte_offset_into_buffer = false;
+ }
+
+ // In case our register definitions don't include the correct offsets,
+ // keep track of the size of each reg & compute offset based on that.
+ uint32_t running_byte_offset = 0;
+ for (uint32_t reg_idx = 0;
+ (reg_info = GetRegisterInfoAtIndex(reg_idx)) != NULL;
+ ++reg_idx, running_byte_offset += reg_info->byte_size) {
+ // Skip composite aka slice registers (e.g. eax is a slice of rax).
+ if (reg_info->value_regs)
+ continue;
+
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+ uint32_t register_offset;
+ if (use_byte_offset_into_buffer) {
+ register_offset = reg_info->byte_offset;
+ } else {
+ register_offset = running_byte_offset;
}
- }
- else
- {
- Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_THREAD | GDBR_LOG_PACKETS));
- if (log)
- {
- if (log->GetVerbose())
- {
- StreamString strm;
- gdb_comm.DumpHistory(strm);
- log->Printf("error: failed to get packet sequence mutex, not sending write all registers:\n%s", strm.GetData());
- }
- else
- log->Printf("error: failed to get packet sequence mutex, not sending write all registers");
+
+ const uint32_t reg_byte_size = reg_info->byte_size;
+
+ const uint8_t *restore_src =
+ restore_data.PeekData(register_offset, reg_byte_size);
+ if (restore_src) {
+ SetRegisterIsValid(reg, false);
+ if (gdb_comm.WriteRegister(
+ m_thread.GetProtocolID(),
+ reg_info->kinds[eRegisterKindProcessPlugin],
+ {restore_src, reg_byte_size}))
+ ++num_restored;
+ }
+ }
+ return num_restored > 0;
+ } else {
+ // For the use_g_packet == false case, we're going to write each register
+ // individually. The data buffer is binary data in this case, instead of
+ // ascii characters.
+
+ bool arm64_debugserver = false;
+ if (m_thread.GetProcess().get()) {
+ const ArchSpec &arch =
+ m_thread.GetProcess()->GetTarget().GetArchitecture();
+ if (arch.IsValid() && arch.GetMachine() == llvm::Triple::aarch64 &&
+ arch.GetTriple().getVendor() == llvm::Triple::Apple &&
+ arch.GetTriple().getOS() == llvm::Triple::IOS) {
+ arm64_debugserver = true;
}
+ }
+ uint32_t num_restored = 0;
+ const RegisterInfo *reg_info;
+ for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL;
+ i++) {
+ if (reg_info->value_regs) // skip registers that are slices of real
+ // registers
+ continue;
+ // Skip the fpsr and fpcr floating point status/control register writing
+ // to
+ // work around a bug in an older version of debugserver that would lead
+ // to
+ // register context corruption when writing fpsr/fpcr.
+ if (arm64_debugserver && (strcmp(reg_info->name, "fpsr") == 0 ||
+ strcmp(reg_info->name, "fpcr") == 0)) {
+ continue;
+ }
+
+ SetRegisterIsValid(reg_info, false);
+ if (gdb_comm.WriteRegister(m_thread.GetProtocolID(),
+ reg_info->kinds[eRegisterKindProcessPlugin],
+ {data_sp->GetBytes() + reg_info->byte_offset,
+ reg_info->byte_size}))
+ ++num_restored;
+ }
+ return num_restored > 0;
}
- return false;
+ } else {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(GDBR_LOG_THREAD |
+ GDBR_LOG_PACKETS));
+ if (log) {
+ if (log->GetVerbose()) {
+ StreamString strm;
+ gdb_comm.DumpHistory(strm);
+ log->Printf("error: failed to get packet sequence mutex, not sending "
+ "write all registers:\n%s",
+ strm.GetData());
+ } else
+ log->Printf("error: failed to get packet sequence mutex, not sending "
+ "write all registers");
+ }
+ }
+ return false;
}
-
-uint32_t
-GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num)
-{
- return m_reg_info.ConvertRegisterKindToRegisterNumber (kind, num);
+uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber(
+ lldb::RegisterKind kind, uint32_t num) {
+ return m_reg_info.ConvertRegisterKindToRegisterNumber(kind, num);
}
-
-void
-GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch)
-{
- // For Advanced SIMD and VFP register mapping.
- static uint32_t g_d0_regs[] = { 26, 27, LLDB_INVALID_REGNUM }; // (s0, s1)
- static uint32_t g_d1_regs[] = { 28, 29, LLDB_INVALID_REGNUM }; // (s2, s3)
- static uint32_t g_d2_regs[] = { 30, 31, LLDB_INVALID_REGNUM }; // (s4, s5)
- static uint32_t g_d3_regs[] = { 32, 33, LLDB_INVALID_REGNUM }; // (s6, s7)
- static uint32_t g_d4_regs[] = { 34, 35, LLDB_INVALID_REGNUM }; // (s8, s9)
- static uint32_t g_d5_regs[] = { 36, 37, LLDB_INVALID_REGNUM }; // (s10, s11)
- static uint32_t g_d6_regs[] = { 38, 39, LLDB_INVALID_REGNUM }; // (s12, s13)
- static uint32_t g_d7_regs[] = { 40, 41, LLDB_INVALID_REGNUM }; // (s14, s15)
- static uint32_t g_d8_regs[] = { 42, 43, LLDB_INVALID_REGNUM }; // (s16, s17)
- static uint32_t g_d9_regs[] = { 44, 45, LLDB_INVALID_REGNUM }; // (s18, s19)
- static uint32_t g_d10_regs[] = { 46, 47, LLDB_INVALID_REGNUM }; // (s20, s21)
- static uint32_t g_d11_regs[] = { 48, 49, LLDB_INVALID_REGNUM }; // (s22, s23)
- static uint32_t g_d12_regs[] = { 50, 51, LLDB_INVALID_REGNUM }; // (s24, s25)
- static uint32_t g_d13_regs[] = { 52, 53, LLDB_INVALID_REGNUM }; // (s26, s27)
- static uint32_t g_d14_regs[] = { 54, 55, LLDB_INVALID_REGNUM }; // (s28, s29)
- static uint32_t g_d15_regs[] = { 56, 57, LLDB_INVALID_REGNUM }; // (s30, s31)
- static uint32_t g_q0_regs[] = { 26, 27, 28, 29, LLDB_INVALID_REGNUM }; // (d0, d1) -> (s0, s1, s2, s3)
- static uint32_t g_q1_regs[] = { 30, 31, 32, 33, LLDB_INVALID_REGNUM }; // (d2, d3) -> (s4, s5, s6, s7)
- static uint32_t g_q2_regs[] = { 34, 35, 36, 37, LLDB_INVALID_REGNUM }; // (d4, d5) -> (s8, s9, s10, s11)
- static uint32_t g_q3_regs[] = { 38, 39, 40, 41, LLDB_INVALID_REGNUM }; // (d6, d7) -> (s12, s13, s14, s15)
- static uint32_t g_q4_regs[] = { 42, 43, 44, 45, LLDB_INVALID_REGNUM }; // (d8, d9) -> (s16, s17, s18, s19)
- static uint32_t g_q5_regs[] = { 46, 47, 48, 49, LLDB_INVALID_REGNUM }; // (d10, d11) -> (s20, s21, s22, s23)
- static uint32_t g_q6_regs[] = { 50, 51, 52, 53, LLDB_INVALID_REGNUM }; // (d12, d13) -> (s24, s25, s26, s27)
- static uint32_t g_q7_regs[] = { 54, 55, 56, 57, LLDB_INVALID_REGNUM }; // (d14, d15) -> (s28, s29, s30, s31)
- static uint32_t g_q8_regs[] = { 59, 60, LLDB_INVALID_REGNUM }; // (d16, d17)
- static uint32_t g_q9_regs[] = { 61, 62, LLDB_INVALID_REGNUM }; // (d18, d19)
- static uint32_t g_q10_regs[] = { 63, 64, LLDB_INVALID_REGNUM }; // (d20, d21)
- static uint32_t g_q11_regs[] = { 65, 66, LLDB_INVALID_REGNUM }; // (d22, d23)
- static uint32_t g_q12_regs[] = { 67, 68, LLDB_INVALID_REGNUM }; // (d24, d25)
- static uint32_t g_q13_regs[] = { 69, 70, LLDB_INVALID_REGNUM }; // (d26, d27)
- static uint32_t g_q14_regs[] = { 71, 72, LLDB_INVALID_REGNUM }; // (d28, d29)
- static uint32_t g_q15_regs[] = { 73, 74, LLDB_INVALID_REGNUM }; // (d30, d31)
-
- // This is our array of composite registers, with each element coming from the above register mappings.
- static uint32_t *g_composites[] = {
- g_d0_regs, g_d1_regs, g_d2_regs, g_d3_regs, g_d4_regs, g_d5_regs, g_d6_regs, g_d7_regs,
- g_d8_regs, g_d9_regs, g_d10_regs, g_d11_regs, g_d12_regs, g_d13_regs, g_d14_regs, g_d15_regs,
- g_q0_regs, g_q1_regs, g_q2_regs, g_q3_regs, g_q4_regs, g_q5_regs, g_q6_regs, g_q7_regs,
- g_q8_regs, g_q9_regs, g_q10_regs, g_q11_regs, g_q12_regs, g_q13_regs, g_q14_regs, g_q15_regs
- };
-
+void GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters(bool from_scratch) {
+ // For Advanced SIMD and VFP register mapping.
+ static uint32_t g_d0_regs[] = {26, 27, LLDB_INVALID_REGNUM}; // (s0, s1)
+ static uint32_t g_d1_regs[] = {28, 29, LLDB_INVALID_REGNUM}; // (s2, s3)
+ static uint32_t g_d2_regs[] = {30, 31, LLDB_INVALID_REGNUM}; // (s4, s5)
+ static uint32_t g_d3_regs[] = {32, 33, LLDB_INVALID_REGNUM}; // (s6, s7)
+ static uint32_t g_d4_regs[] = {34, 35, LLDB_INVALID_REGNUM}; // (s8, s9)
+ static uint32_t g_d5_regs[] = {36, 37, LLDB_INVALID_REGNUM}; // (s10, s11)
+ static uint32_t g_d6_regs[] = {38, 39, LLDB_INVALID_REGNUM}; // (s12, s13)
+ static uint32_t g_d7_regs[] = {40, 41, LLDB_INVALID_REGNUM}; // (s14, s15)
+ static uint32_t g_d8_regs[] = {42, 43, LLDB_INVALID_REGNUM}; // (s16, s17)
+ static uint32_t g_d9_regs[] = {44, 45, LLDB_INVALID_REGNUM}; // (s18, s19)
+ static uint32_t g_d10_regs[] = {46, 47, LLDB_INVALID_REGNUM}; // (s20, s21)
+ static uint32_t g_d11_regs[] = {48, 49, LLDB_INVALID_REGNUM}; // (s22, s23)
+ static uint32_t g_d12_regs[] = {50, 51, LLDB_INVALID_REGNUM}; // (s24, s25)
+ static uint32_t g_d13_regs[] = {52, 53, LLDB_INVALID_REGNUM}; // (s26, s27)
+ static uint32_t g_d14_regs[] = {54, 55, LLDB_INVALID_REGNUM}; // (s28, s29)
+ static uint32_t g_d15_regs[] = {56, 57, LLDB_INVALID_REGNUM}; // (s30, s31)
+ static uint32_t g_q0_regs[] = {
+ 26, 27, 28, 29, LLDB_INVALID_REGNUM}; // (d0, d1) -> (s0, s1, s2, s3)
+ static uint32_t g_q1_regs[] = {
+ 30, 31, 32, 33, LLDB_INVALID_REGNUM}; // (d2, d3) -> (s4, s5, s6, s7)
+ static uint32_t g_q2_regs[] = {
+ 34, 35, 36, 37, LLDB_INVALID_REGNUM}; // (d4, d5) -> (s8, s9, s10, s11)
+ static uint32_t g_q3_regs[] = {
+ 38, 39, 40, 41, LLDB_INVALID_REGNUM}; // (d6, d7) -> (s12, s13, s14, s15)
+ static uint32_t g_q4_regs[] = {
+ 42, 43, 44, 45, LLDB_INVALID_REGNUM}; // (d8, d9) -> (s16, s17, s18, s19)
+ static uint32_t g_q5_regs[] = {
+ 46, 47, 48, 49,
+ LLDB_INVALID_REGNUM}; // (d10, d11) -> (s20, s21, s22, s23)
+ static uint32_t g_q6_regs[] = {
+ 50, 51, 52, 53,
+ LLDB_INVALID_REGNUM}; // (d12, d13) -> (s24, s25, s26, s27)
+ static uint32_t g_q7_regs[] = {
+ 54, 55, 56, 57,
+ LLDB_INVALID_REGNUM}; // (d14, d15) -> (s28, s29, s30, s31)
+ static uint32_t g_q8_regs[] = {59, 60, LLDB_INVALID_REGNUM}; // (d16, d17)
+ static uint32_t g_q9_regs[] = {61, 62, LLDB_INVALID_REGNUM}; // (d18, d19)
+ static uint32_t g_q10_regs[] = {63, 64, LLDB_INVALID_REGNUM}; // (d20, d21)
+ static uint32_t g_q11_regs[] = {65, 66, LLDB_INVALID_REGNUM}; // (d22, d23)
+ static uint32_t g_q12_regs[] = {67, 68, LLDB_INVALID_REGNUM}; // (d24, d25)
+ static uint32_t g_q13_regs[] = {69, 70, LLDB_INVALID_REGNUM}; // (d26, d27)
+ static uint32_t g_q14_regs[] = {71, 72, LLDB_INVALID_REGNUM}; // (d28, d29)
+ static uint32_t g_q15_regs[] = {73, 74, LLDB_INVALID_REGNUM}; // (d30, d31)
+
+ // This is our array of composite registers, with each element coming from the
+ // above register mappings.
+ static uint32_t *g_composites[] = {
+ g_d0_regs, g_d1_regs, g_d2_regs, g_d3_regs, g_d4_regs, g_d5_regs,
+ g_d6_regs, g_d7_regs, g_d8_regs, g_d9_regs, g_d10_regs, g_d11_regs,
+ g_d12_regs, g_d13_regs, g_d14_regs, g_d15_regs, g_q0_regs, g_q1_regs,
+ g_q2_regs, g_q3_regs, g_q4_regs, g_q5_regs, g_q6_regs, g_q7_regs,
+ g_q8_regs, g_q9_regs, g_q10_regs, g_q11_regs, g_q12_regs, g_q13_regs,
+ g_q14_regs, g_q15_regs};
+
+ // clang-format off
static RegisterInfo g_register_infos[] = {
-// NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATE REGS
-// ====== ====== === === ============= ============ =================== =================== ====================== ============= ==== ========== ===============
- { "r0", "arg1", 4, 0, eEncodingUint, eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1,0, 0 }, NULL, NULL},
- { "r1", "arg2", 4, 0, eEncodingUint, eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2,1, 1 }, NULL, NULL},
- { "r2", "arg3", 4, 0, eEncodingUint, eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3,2, 2 }, NULL, NULL},
- { "r3", "arg4", 4, 0, eEncodingUint, eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4,3, 3 }, NULL, NULL},
- { "r4", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, 4, 4 }, NULL, NULL},
- { "r5", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, 5, 5 }, NULL, NULL},
- { "r6", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, 6, 6 }, NULL, NULL},
- { "r7", "fp", 4, 0, eEncodingUint, eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, 7, 7 }, NULL, NULL},
- { "r8", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, 8, 8 }, NULL, NULL},
- { "r9", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, 9, 9 }, NULL, NULL},
- { "r10", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, 10, 10 }, NULL, NULL},
- { "r11", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, 11, 11 }, NULL, NULL},
- { "r12", NULL, 4, 0, eEncodingUint, eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, 12, 12 }, NULL, NULL},
- { "sp", "r13", 4, 0, eEncodingUint, eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, 13, 13 }, NULL, NULL},
- { "lr", "r14", 4, 0, eEncodingUint, eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, 14, 14 }, NULL, NULL},
- { "pc", "r15", 4, 0, eEncodingUint, eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, 15, 15 }, NULL, NULL},
- { "f0", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 16, 16 }, NULL, NULL},
- { "f1", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 17, 17 }, NULL, NULL},
- { "f2", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 18, 18 }, NULL, NULL},
- { "f3", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 19, 19 }, NULL, NULL},
- { "f4", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 20, 20 }, NULL, NULL},
- { "f5", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 21, 21 }, NULL, NULL},
- { "f6", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 22, 22 }, NULL, NULL},
- { "f7", NULL, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 23, 23 }, NULL, NULL},
- { "fps", NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 24, 24 }, NULL, NULL},
- { "cpsr","flags", 4, 0, eEncodingUint, eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_INVALID_REGNUM, 25, 25 }, NULL, NULL},
- { "s0", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, 26, 26 }, NULL, NULL},
- { "s1", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, 27, 27 }, NULL, NULL},
- { "s2", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, 28, 28 }, NULL, NULL},
- { "s3", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, 29, 29 }, NULL, NULL},
- { "s4", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, 30, 30 }, NULL, NULL},
- { "s5", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, 31, 31 }, NULL, NULL},
- { "s6", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, 32, 32 }, NULL, NULL},
- { "s7", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, 33, 33 }, NULL, NULL},
- { "s8", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, 34, 34 }, NULL, NULL},
- { "s9", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, 35, 35 }, NULL, NULL},
- { "s10", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, 36, 36 }, NULL, NULL},
- { "s11", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, 37, 37 }, NULL, NULL},
- { "s12", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, 38, 38 }, NULL, NULL},
- { "s13", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, 39, 39 }, NULL, NULL},
- { "s14", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, 40, 40 }, NULL, NULL},
- { "s15", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, 41, 41 }, NULL, NULL},
- { "s16", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, 42, 42 }, NULL, NULL},
- { "s17", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, 43, 43 }, NULL, NULL},
- { "s18", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, 44, 44 }, NULL, NULL},
- { "s19", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, 45, 45 }, NULL, NULL},
- { "s20", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, 46, 46 }, NULL, NULL},
- { "s21", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, 47, 47 }, NULL, NULL},
- { "s22", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, 48, 48 }, NULL, NULL},
- { "s23", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, 49, 49 }, NULL, NULL},
- { "s24", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, 50, 50 }, NULL, NULL},
- { "s25", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, 51, 51 }, NULL, NULL},
- { "s26", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, 52, 52 }, NULL, NULL},
- { "s27", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, 53, 53 }, NULL, NULL},
- { "s28", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, 54, 54 }, NULL, NULL},
- { "s29", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, 55, 55 }, NULL, NULL},
- { "s30", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, 56, 56 }, NULL, NULL},
- { "s31", NULL, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, 57, 57 }, NULL, NULL},
- { "fpscr",NULL, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 58, 58 }, NULL, NULL},
- { "d16", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, 59, 59 }, NULL, NULL},
- { "d17", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, 60, 60 }, NULL, NULL},
- { "d18", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, 61, 61 }, NULL, NULL},
- { "d19", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, 62, 62 }, NULL, NULL},
- { "d20", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, 63, 63 }, NULL, NULL},
- { "d21", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, 64, 64 }, NULL, NULL},
- { "d22", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, 65, 65 }, NULL, NULL},
- { "d23", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, 66, 66 }, NULL, NULL},
- { "d24", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, 67, 67 }, NULL, NULL},
- { "d25", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, 68, 68 }, NULL, NULL},
- { "d26", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, 69, 69 }, NULL, NULL},
- { "d27", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, 70, 70 }, NULL, NULL},
- { "d28", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, 71, 71 }, NULL, NULL},
- { "d29", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, 72, 72 }, NULL, NULL},
- { "d30", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, 73, 73 }, NULL, NULL},
- { "d31", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, 74, 74 }, NULL, NULL},
- { "d0", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, 75, 75 }, g_d0_regs, NULL},
- { "d1", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, 76, 76 }, g_d1_regs, NULL},
- { "d2", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, 77, 77 }, g_d2_regs, NULL},
- { "d3", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, 78, 78 }, g_d3_regs, NULL},
- { "d4", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, 79, 79 }, g_d4_regs, NULL},
- { "d5", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, 80, 80 }, g_d5_regs, NULL},
- { "d6", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, 81, 81 }, g_d6_regs, NULL},
- { "d7", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, 82, 82 }, g_d7_regs, NULL},
- { "d8", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, 83, 83 }, g_d8_regs, NULL},
- { "d9", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, 84, 84 }, g_d9_regs, NULL},
- { "d10", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, 85, 85 }, g_d10_regs, NULL},
- { "d11", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, 86, 86 }, g_d11_regs, NULL},
- { "d12", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, 87, 87 }, g_d12_regs, NULL},
- { "d13", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, 88, 88 }, g_d13_regs, NULL},
- { "d14", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, 89, 89 }, g_d14_regs, NULL},
- { "d15", NULL, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, 90, 90 }, g_d15_regs, NULL},
- { "q0", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0, LLDB_INVALID_REGNUM, 91, 91 }, g_q0_regs, NULL},
- { "q1", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1, LLDB_INVALID_REGNUM, 92, 92 }, g_q1_regs, NULL},
- { "q2", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2, LLDB_INVALID_REGNUM, 93, 93 }, g_q2_regs, NULL},
- { "q3", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3, LLDB_INVALID_REGNUM, 94, 94 }, g_q3_regs, NULL},
- { "q4", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4, LLDB_INVALID_REGNUM, 95, 95 }, g_q4_regs, NULL},
- { "q5", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5, LLDB_INVALID_REGNUM, 96, 96 }, g_q5_regs, NULL},
- { "q6", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6, LLDB_INVALID_REGNUM, 97, 97 }, g_q6_regs, NULL},
- { "q7", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7, LLDB_INVALID_REGNUM, 98, 98 }, g_q7_regs, NULL},
- { "q8", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8, LLDB_INVALID_REGNUM, 99, 99 }, g_q8_regs, NULL},
- { "q9", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9, LLDB_INVALID_REGNUM, 100, 100 }, g_q9_regs, NULL},
- { "q10", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10, LLDB_INVALID_REGNUM, 101, 101 }, g_q10_regs, NULL},
- { "q11", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11, LLDB_INVALID_REGNUM, 102, 102 }, g_q11_regs, NULL},
- { "q12", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12, LLDB_INVALID_REGNUM, 103, 103 }, g_q12_regs, NULL},
- { "q13", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13, LLDB_INVALID_REGNUM, 104, 104 }, g_q13_regs, NULL},
- { "q14", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, 105, 105 }, g_q14_regs, NULL},
- { "q15", NULL, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, 106, 106 }, g_q15_regs, NULL}
+// NAME ALT SZ OFF ENCODING FORMAT EH_FRAME DWARF GENERIC PROCESS PLUGIN LLDB VALUE REGS INVALIDATE REGS SIZE EXPR SIZE LEN
+// ====== ====== === === ============= ========== =================== =================== ====================== ============= ==== ========== =============== ========= ========
+ { "r0", "arg1", 4, 0, eEncodingUint, eFormatHex, { ehframe_r0, dwarf_r0, LLDB_REGNUM_GENERIC_ARG1,0, 0 }, nullptr, nullptr, nullptr, 0 },
+ { "r1", "arg2", 4, 0, eEncodingUint, eFormatHex, { ehframe_r1, dwarf_r1, LLDB_REGNUM_GENERIC_ARG2,1, 1 }, nullptr, nullptr, nullptr, 0 },
+ { "r2", "arg3", 4, 0, eEncodingUint, eFormatHex, { ehframe_r2, dwarf_r2, LLDB_REGNUM_GENERIC_ARG3,2, 2 }, nullptr, nullptr, nullptr, 0 },
+ { "r3", "arg4", 4, 0, eEncodingUint, eFormatHex, { ehframe_r3, dwarf_r3, LLDB_REGNUM_GENERIC_ARG4,3, 3 }, nullptr, nullptr, nullptr, 0 },
+ { "r4", nullptr, 4, 0, eEncodingUint, eFormatHex, { ehframe_r4, dwarf_r4, LLDB_INVALID_REGNUM, 4, 4 }, nullptr, nullptr, nullptr, 0 },
+ { "r5", nullptr, 4, 0, eEncodingUint, eFormatHex, { ehframe_r5, dwarf_r5, LLDB_INVALID_REGNUM, 5, 5 }, nullptr, nullptr, nullptr, 0 },
+ { "r6", nullptr, 4, 0, eEncodingUint, eFormatHex, { ehframe_r6, dwarf_r6, LLDB_INVALID_REGNUM, 6, 6 }, nullptr, nullptr, nullptr, 0 },
+ { "r7", "fp", 4, 0, eEncodingUint, eFormatHex, { ehframe_r7, dwarf_r7, LLDB_REGNUM_GENERIC_FP, 7, 7 }, nullptr, nullptr, nullptr, 0 },
+ { "r8", nullptr, 4, 0, eEncodingUint, eFormatHex, { ehframe_r8, dwarf_r8, LLDB_INVALID_REGNUM, 8, 8 }, nullptr, nullptr, nullptr, 0 },
+ { "r9", nullptr, 4, 0, eEncodingUint, eFormatHex, { ehframe_r9, dwarf_r9, LLDB_INVALID_REGNUM, 9, 9 }, nullptr, nullptr, nullptr, 0 },
+ { "r10", nullptr, 4, 0, eEncodingUint, eFormatHex, { ehframe_r10, dwarf_r10, LLDB_INVALID_REGNUM, 10, 10 }, nullptr, nullptr, nullptr, 0 },
+ { "r11", nullptr, 4, 0, eEncodingUint, eFormatHex, { ehframe_r11, dwarf_r11, LLDB_INVALID_REGNUM, 11, 11 }, nullptr, nullptr, nullptr, 0 },
+ { "r12", nullptr, 4, 0, eEncodingUint, eFormatHex, { ehframe_r12, dwarf_r12, LLDB_INVALID_REGNUM, 12, 12 }, nullptr, nullptr, nullptr, 0 },
+ { "sp", "r13", 4, 0, eEncodingUint, eFormatHex, { ehframe_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, 13, 13 }, nullptr, nullptr, nullptr, 0 },
+ { "lr", "r14", 4, 0, eEncodingUint, eFormatHex, { ehframe_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, 14, 14 }, nullptr, nullptr, nullptr, 0 },
+ { "pc", "r15", 4, 0, eEncodingUint, eFormatHex, { ehframe_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, 15, 15 }, nullptr, nullptr, nullptr, 0 },
+ { "f0", nullptr, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 16, 16 }, nullptr, nullptr, nullptr, 0 },
+ { "f1", nullptr, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 17, 17 }, nullptr, nullptr, nullptr, 0 },
+ { "f2", nullptr, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 18, 18 }, nullptr, nullptr, nullptr, 0 },
+ { "f3", nullptr, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 19, 19 }, nullptr, nullptr, nullptr, 0 },
+ { "f4", nullptr, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 20, 20 }, nullptr, nullptr, nullptr, 0 },
+ { "f5", nullptr, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 21, 21 }, nullptr, nullptr, nullptr, 0 },
+ { "f6", nullptr, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 22, 22 }, nullptr, nullptr, nullptr, 0 },
+ { "f7", nullptr, 12, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 23, 23 }, nullptr, nullptr, nullptr, 0 },
+ { "fps", nullptr, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 24, 24 }, nullptr, nullptr, nullptr, 0 },
+ { "cpsr","flags", 4, 0, eEncodingUint, eFormatHex, { ehframe_cpsr, dwarf_cpsr, LLDB_INVALID_REGNUM, 25, 25 }, nullptr, nullptr, nullptr, 0 },
+ { "s0", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, 26, 26 }, nullptr, nullptr, nullptr, 0 },
+ { "s1", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, 27, 27 }, nullptr, nullptr, nullptr, 0 },
+ { "s2", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s2, LLDB_INVALID_REGNUM, 28, 28 }, nullptr, nullptr, nullptr, 0 },
+ { "s3", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s3, LLDB_INVALID_REGNUM, 29, 29 }, nullptr, nullptr, nullptr, 0 },
+ { "s4", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s4, LLDB_INVALID_REGNUM, 30, 30 }, nullptr, nullptr, nullptr, 0 },
+ { "s5", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s5, LLDB_INVALID_REGNUM, 31, 31 }, nullptr, nullptr, nullptr, 0 },
+ { "s6", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s6, LLDB_INVALID_REGNUM, 32, 32 }, nullptr, nullptr, nullptr, 0 },
+ { "s7", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s7, LLDB_INVALID_REGNUM, 33, 33 }, nullptr, nullptr, nullptr, 0 },
+ { "s8", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s8, LLDB_INVALID_REGNUM, 34, 34 }, nullptr, nullptr, nullptr, 0 },
+ { "s9", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s9, LLDB_INVALID_REGNUM, 35, 35 }, nullptr, nullptr, nullptr, 0 },
+ { "s10", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s10, LLDB_INVALID_REGNUM, 36, 36 }, nullptr, nullptr, nullptr, 0 },
+ { "s11", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s11, LLDB_INVALID_REGNUM, 37, 37 }, nullptr, nullptr, nullptr, 0 },
+ { "s12", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s12, LLDB_INVALID_REGNUM, 38, 38 }, nullptr, nullptr, nullptr, 0 },
+ { "s13", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s13, LLDB_INVALID_REGNUM, 39, 39 }, nullptr, nullptr, nullptr, 0 },
+ { "s14", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s14, LLDB_INVALID_REGNUM, 40, 40 }, nullptr, nullptr, nullptr, 0 },
+ { "s15", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s15, LLDB_INVALID_REGNUM, 41, 41 }, nullptr, nullptr, nullptr, 0 },
+ { "s16", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s16, LLDB_INVALID_REGNUM, 42, 42 }, nullptr, nullptr, nullptr, 0 },
+ { "s17", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s17, LLDB_INVALID_REGNUM, 43, 43 }, nullptr, nullptr, nullptr, 0 },
+ { "s18", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s18, LLDB_INVALID_REGNUM, 44, 44 }, nullptr, nullptr, nullptr, 0 },
+ { "s19", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s19, LLDB_INVALID_REGNUM, 45, 45 }, nullptr, nullptr, nullptr, 0 },
+ { "s20", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s20, LLDB_INVALID_REGNUM, 46, 46 }, nullptr, nullptr, nullptr, 0 },
+ { "s21", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s21, LLDB_INVALID_REGNUM, 47, 47 }, nullptr, nullptr, nullptr, 0 },
+ { "s22", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s22, LLDB_INVALID_REGNUM, 48, 48 }, nullptr, nullptr, nullptr, 0 },
+ { "s23", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s23, LLDB_INVALID_REGNUM, 49, 49 }, nullptr, nullptr, nullptr, 0 },
+ { "s24", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s24, LLDB_INVALID_REGNUM, 50, 50 }, nullptr, nullptr, nullptr, 0 },
+ { "s25", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s25, LLDB_INVALID_REGNUM, 51, 51 }, nullptr, nullptr, nullptr, 0 },
+ { "s26", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s26, LLDB_INVALID_REGNUM, 52, 52 }, nullptr, nullptr, nullptr, 0 },
+ { "s27", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s27, LLDB_INVALID_REGNUM, 53, 53 }, nullptr, nullptr, nullptr, 0 },
+ { "s28", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s28, LLDB_INVALID_REGNUM, 54, 54 }, nullptr, nullptr, nullptr, 0 },
+ { "s29", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s29, LLDB_INVALID_REGNUM, 55, 55 }, nullptr, nullptr, nullptr, 0 },
+ { "s30", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s30, LLDB_INVALID_REGNUM, 56, 56 }, nullptr, nullptr, nullptr, 0 },
+ { "s31", nullptr, 4, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s31, LLDB_INVALID_REGNUM, 57, 57 }, nullptr, nullptr, nullptr, 0 },
+ { "fpscr",nullptr, 4, 0, eEncodingUint, eFormatHex, { LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 58, 58 }, nullptr, nullptr, nullptr, 0 },
+ { "d16", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d16, LLDB_INVALID_REGNUM, 59, 59 }, nullptr, nullptr, nullptr, 0 },
+ { "d17", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d17, LLDB_INVALID_REGNUM, 60, 60 }, nullptr, nullptr, nullptr, 0 },
+ { "d18", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d18, LLDB_INVALID_REGNUM, 61, 61 }, nullptr, nullptr, nullptr, 0 },
+ { "d19", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d19, LLDB_INVALID_REGNUM, 62, 62 }, nullptr, nullptr, nullptr, 0 },
+ { "d20", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d20, LLDB_INVALID_REGNUM, 63, 63 }, nullptr, nullptr, nullptr, 0 },
+ { "d21", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d21, LLDB_INVALID_REGNUM, 64, 64 }, nullptr, nullptr, nullptr, 0 },
+ { "d22", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d22, LLDB_INVALID_REGNUM, 65, 65 }, nullptr, nullptr, nullptr, 0 },
+ { "d23", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d23, LLDB_INVALID_REGNUM, 66, 66 }, nullptr, nullptr, nullptr, 0 },
+ { "d24", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d24, LLDB_INVALID_REGNUM, 67, 67 }, nullptr, nullptr, nullptr, 0 },
+ { "d25", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d25, LLDB_INVALID_REGNUM, 68, 68 }, nullptr, nullptr, nullptr, 0 },
+ { "d26", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d26, LLDB_INVALID_REGNUM, 69, 69 }, nullptr, nullptr, nullptr, 0 },
+ { "d27", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d27, LLDB_INVALID_REGNUM, 70, 70 }, nullptr, nullptr, nullptr, 0 },
+ { "d28", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d28, LLDB_INVALID_REGNUM, 71, 71 }, nullptr, nullptr, nullptr, 0 },
+ { "d29", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d29, LLDB_INVALID_REGNUM, 72, 72 }, nullptr, nullptr, nullptr, 0 },
+ { "d30", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d30, LLDB_INVALID_REGNUM, 73, 73 }, nullptr, nullptr, nullptr, 0 },
+ { "d31", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d31, LLDB_INVALID_REGNUM, 74, 74 }, nullptr, nullptr, nullptr, 0 },
+ { "d0", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d0, LLDB_INVALID_REGNUM, 75, 75 }, g_d0_regs, nullptr, nullptr, 0 },
+ { "d1", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d1, LLDB_INVALID_REGNUM, 76, 76 }, g_d1_regs, nullptr, nullptr, 0 },
+ { "d2", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d2, LLDB_INVALID_REGNUM, 77, 77 }, g_d2_regs, nullptr, nullptr, 0 },
+ { "d3", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d3, LLDB_INVALID_REGNUM, 78, 78 }, g_d3_regs, nullptr, nullptr, 0 },
+ { "d4", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d4, LLDB_INVALID_REGNUM, 79, 79 }, g_d4_regs, nullptr, nullptr, 0 },
+ { "d5", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d5, LLDB_INVALID_REGNUM, 80, 80 }, g_d5_regs, nullptr, nullptr, 0 },
+ { "d6", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d6, LLDB_INVALID_REGNUM, 81, 81 }, g_d6_regs, nullptr, nullptr, 0 },
+ { "d7", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d7, LLDB_INVALID_REGNUM, 82, 82 }, g_d7_regs, nullptr, nullptr, 0 },
+ { "d8", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d8, LLDB_INVALID_REGNUM, 83, 83 }, g_d8_regs, nullptr, nullptr, 0 },
+ { "d9", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d9, LLDB_INVALID_REGNUM, 84, 84 }, g_d9_regs, nullptr, nullptr, 0 },
+ { "d10", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d10, LLDB_INVALID_REGNUM, 85, 85 }, g_d10_regs, nullptr, nullptr, 0 },
+ { "d11", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d11, LLDB_INVALID_REGNUM, 86, 86 }, g_d11_regs, nullptr, nullptr, 0 },
+ { "d12", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d12, LLDB_INVALID_REGNUM, 87, 87 }, g_d12_regs, nullptr, nullptr, 0 },
+ { "d13", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d13, LLDB_INVALID_REGNUM, 88, 88 }, g_d13_regs, nullptr, nullptr, 0 },
+ { "d14", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d14, LLDB_INVALID_REGNUM, 89, 89 }, g_d14_regs, nullptr, nullptr, 0 },
+ { "d15", nullptr, 8, 0, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_d15, LLDB_INVALID_REGNUM, 90, 90 }, g_d15_regs, nullptr, nullptr, 0 },
+ { "q0", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q0, LLDB_INVALID_REGNUM, 91, 91 }, g_q0_regs, nullptr, nullptr, 0 },
+ { "q1", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q1, LLDB_INVALID_REGNUM, 92, 92 }, g_q1_regs, nullptr, nullptr, 0 },
+ { "q2", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q2, LLDB_INVALID_REGNUM, 93, 93 }, g_q2_regs, nullptr, nullptr, 0 },
+ { "q3", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q3, LLDB_INVALID_REGNUM, 94, 94 }, g_q3_regs, nullptr, nullptr, 0 },
+ { "q4", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q4, LLDB_INVALID_REGNUM, 95, 95 }, g_q4_regs, nullptr, nullptr, 0 },
+ { "q5", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q5, LLDB_INVALID_REGNUM, 96, 96 }, g_q5_regs, nullptr, nullptr, 0 },
+ { "q6", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q6, LLDB_INVALID_REGNUM, 97, 97 }, g_q6_regs, nullptr, nullptr, 0 },
+ { "q7", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q7, LLDB_INVALID_REGNUM, 98, 98 }, g_q7_regs, nullptr, nullptr, 0 },
+ { "q8", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q8, LLDB_INVALID_REGNUM, 99, 99 }, g_q8_regs, nullptr, nullptr, 0 },
+ { "q9", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q9, LLDB_INVALID_REGNUM, 100, 100 }, g_q9_regs, nullptr, nullptr, 0 },
+ { "q10", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q10, LLDB_INVALID_REGNUM, 101, 101 }, g_q10_regs, nullptr, nullptr, 0 },
+ { "q11", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q11, LLDB_INVALID_REGNUM, 102, 102 }, g_q11_regs, nullptr, nullptr, 0 },
+ { "q12", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q12, LLDB_INVALID_REGNUM, 103, 103 }, g_q12_regs, nullptr, nullptr, 0 },
+ { "q13", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q13, LLDB_INVALID_REGNUM, 104, 104 }, g_q13_regs, nullptr, nullptr, 0 },
+ { "q14", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q14, LLDB_INVALID_REGNUM, 105, 105 }, g_q14_regs, nullptr, nullptr, 0 },
+ { "q15", nullptr, 16, 0, eEncodingVector, eFormatVectorOfUInt8, { LLDB_INVALID_REGNUM, dwarf_q15, LLDB_INVALID_REGNUM, 106, 106 }, g_q15_regs, nullptr, nullptr, 0 }
};
-
- static const uint32_t num_registers = llvm::array_lengthof(g_register_infos);
- static ConstString gpr_reg_set ("General Purpose Registers");
- static ConstString sfp_reg_set ("Software Floating Point Registers");
- static ConstString vfp_reg_set ("Floating Point Registers");
- size_t i;
- if (from_scratch)
- {
- // Calculate the offsets of the registers
- // Note that the layout of the "composite" registers (d0-d15 and q0-q15) which comes after the
- // "primordial" registers is important. This enables us to calculate the offset of the composite
- // register by using the offset of its first primordial register. For example, to calculate the
- // offset of q0, use s0's offset.
- if (g_register_infos[2].byte_offset == 0)
- {
- uint32_t byte_offset = 0;
- for (i=0; i<num_registers; ++i)
- {
- // For primordial registers, increment the byte_offset by the byte_size to arrive at the
- // byte_offset for the next register. Otherwise, we have a composite register whose
- // offset can be calculated by consulting the offset of its first primordial register.
- if (!g_register_infos[i].value_regs)
- {
- g_register_infos[i].byte_offset = byte_offset;
- byte_offset += g_register_infos[i].byte_size;
- }
- else
- {
- const uint32_t first_primordial_reg = g_register_infos[i].value_regs[0];
- g_register_infos[i].byte_offset = g_register_infos[first_primordial_reg].byte_offset;
- }
- }
- }
- for (i=0; i<num_registers; ++i)
- {
- ConstString name;
- ConstString alt_name;
- if (g_register_infos[i].name && g_register_infos[i].name[0])
- name.SetCString(g_register_infos[i].name);
- if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0])
- alt_name.SetCString(g_register_infos[i].alt_name);
-
- if (i <= 15 || i == 25)
- AddRegister (g_register_infos[i], name, alt_name, gpr_reg_set);
- else if (i <= 24)
- AddRegister (g_register_infos[i], name, alt_name, sfp_reg_set);
- else
- AddRegister (g_register_infos[i], name, alt_name, vfp_reg_set);
+ // clang-format on
+
+ static const uint32_t num_registers = llvm::array_lengthof(g_register_infos);
+ static ConstString gpr_reg_set("General Purpose Registers");
+ static ConstString sfp_reg_set("Software Floating Point Registers");
+ static ConstString vfp_reg_set("Floating Point Registers");
+ size_t i;
+ if (from_scratch) {
+ // Calculate the offsets of the registers
+ // Note that the layout of the "composite" registers (d0-d15 and q0-q15)
+ // which comes after the
+ // "primordial" registers is important. This enables us to calculate the
+ // offset of the composite
+ // register by using the offset of its first primordial register. For
+ // example, to calculate the
+ // offset of q0, use s0's offset.
+ if (g_register_infos[2].byte_offset == 0) {
+ uint32_t byte_offset = 0;
+ for (i = 0; i < num_registers; ++i) {
+ // For primordial registers, increment the byte_offset by the byte_size
+ // to arrive at the
+ // byte_offset for the next register. Otherwise, we have a composite
+ // register whose
+ // offset can be calculated by consulting the offset of its first
+ // primordial register.
+ if (!g_register_infos[i].value_regs) {
+ g_register_infos[i].byte_offset = byte_offset;
+ byte_offset += g_register_infos[i].byte_size;
+ } else {
+ const uint32_t first_primordial_reg =
+ g_register_infos[i].value_regs[0];
+ g_register_infos[i].byte_offset =
+ g_register_infos[first_primordial_reg].byte_offset;
}
+ }
}
- else
- {
- // Add composite registers to our primordial registers, then.
- const size_t num_composites = llvm::array_lengthof(g_composites);
- const size_t num_dynamic_regs = GetNumRegisters();
- const size_t num_common_regs = num_registers - num_composites;
- RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs;
-
- // First we need to validate that all registers that we already have match the non composite regs.
- // If so, then we can add the registers, else we need to bail
- bool match = true;
- if (num_dynamic_regs == num_common_regs)
- {
- for (i=0; match && i<num_dynamic_regs; ++i)
- {
- // Make sure all register names match
- if (m_regs[i].name && g_register_infos[i].name)
- {
- if (strcmp(m_regs[i].name, g_register_infos[i].name))
- {
- match = false;
- break;
- }
- }
-
- // Make sure all register byte sizes match
- if (m_regs[i].byte_size != g_register_infos[i].byte_size)
- {
- match = false;
- break;
- }
- }
- }
- else
- {
- // Wrong number of registers.
+ for (i = 0; i < num_registers; ++i) {
+ ConstString name;
+ ConstString alt_name;
+ if (g_register_infos[i].name && g_register_infos[i].name[0])
+ name.SetCString(g_register_infos[i].name);
+ if (g_register_infos[i].alt_name && g_register_infos[i].alt_name[0])
+ alt_name.SetCString(g_register_infos[i].alt_name);
+
+ if (i <= 15 || i == 25)
+ AddRegister(g_register_infos[i], name, alt_name, gpr_reg_set);
+ else if (i <= 24)
+ AddRegister(g_register_infos[i], name, alt_name, sfp_reg_set);
+ else
+ AddRegister(g_register_infos[i], name, alt_name, vfp_reg_set);
+ }
+ } else {
+ // Add composite registers to our primordial registers, then.
+ const size_t num_composites = llvm::array_lengthof(g_composites);
+ const size_t num_dynamic_regs = GetNumRegisters();
+ const size_t num_common_regs = num_registers - num_composites;
+ RegisterInfo *g_comp_register_infos = g_register_infos + num_common_regs;
+
+ // First we need to validate that all registers that we already have match
+ // the non composite regs.
+ // If so, then we can add the registers, else we need to bail
+ bool match = true;
+ if (num_dynamic_regs == num_common_regs) {
+ for (i = 0; match && i < num_dynamic_regs; ++i) {
+ // Make sure all register names match
+ if (m_regs[i].name && g_register_infos[i].name) {
+ if (strcmp(m_regs[i].name, g_register_infos[i].name)) {
match = false;
+ break;
+ }
}
- // If "match" is true, then we can add extra registers.
- if (match)
- {
- for (i=0; i<num_composites; ++i)
- {
- ConstString name;
- ConstString alt_name;
- const uint32_t first_primordial_reg = g_comp_register_infos[i].value_regs[0];
- const char *reg_name = g_register_infos[first_primordial_reg].name;
- if (reg_name && reg_name[0])
- {
- for (uint32_t j = 0; j < num_dynamic_regs; ++j)
- {
- const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j);
- // Find a matching primordial register info entry.
- if (reg_info && reg_info->name && ::strcasecmp(reg_info->name, reg_name) == 0)
- {
- // The name matches the existing primordial entry.
- // Find and assign the offset, and then add this composite register entry.
- g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
- name.SetCString(g_comp_register_infos[i].name);
- AddRegister(g_comp_register_infos[i], name, alt_name, vfp_reg_set);
- }
- }
- }
+
+ // Make sure all register byte sizes match
+ if (m_regs[i].byte_size != g_register_infos[i].byte_size) {
+ match = false;
+ break;
+ }
+ }
+ } else {
+ // Wrong number of registers.
+ match = false;
+ }
+ // If "match" is true, then we can add extra registers.
+ if (match) {
+ for (i = 0; i < num_composites; ++i) {
+ ConstString name;
+ ConstString alt_name;
+ const uint32_t first_primordial_reg =
+ g_comp_register_infos[i].value_regs[0];
+ const char *reg_name = g_register_infos[first_primordial_reg].name;
+ if (reg_name && reg_name[0]) {
+ for (uint32_t j = 0; j < num_dynamic_regs; ++j) {
+ const RegisterInfo *reg_info = GetRegisterInfoAtIndex(j);
+ // Find a matching primordial register info entry.
+ if (reg_info && reg_info->name &&
+ ::strcasecmp(reg_info->name, reg_name) == 0) {
+ // The name matches the existing primordial entry.
+ // Find and assign the offset, and then add this composite
+ // register entry.
+ g_comp_register_infos[i].byte_offset = reg_info->byte_offset;
+ name.SetCString(g_comp_register_infos[i].name);
+ AddRegister(g_comp_register_infos[i], name, alt_name,
+ vfp_reg_set);
}
+ }
}
+ }
}
+ }
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 0e26c69..5b3e04e 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -16,12 +16,12 @@
// Other libraries and framework includes
// Project includes
-#include "lldb/lldb-private.h"
-#include "lldb/lldb-enumerations.h"
+#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Target/RegisterContext.h"
-#include "Plugins/Process/Utility/DynamicRegisterInfo.h"
+#include "lldb/lldb-enumerations.h"
+#include "lldb/lldb-private.h"
#include "GDBRemoteCommunicationClient.h"
@@ -33,133 +33,102 @@ namespace process_gdb_remote {
class ThreadGDBRemote;
class ProcessGDBRemote;
-class GDBRemoteDynamicRegisterInfo :
- public DynamicRegisterInfo
-{
+class GDBRemoteDynamicRegisterInfo : public DynamicRegisterInfo {
public:
- GDBRemoteDynamicRegisterInfo () :
- DynamicRegisterInfo()
- {
- }
+ GDBRemoteDynamicRegisterInfo() : DynamicRegisterInfo() {}
- ~GDBRemoteDynamicRegisterInfo() override = default;
+ ~GDBRemoteDynamicRegisterInfo() override = default;
- void
- HardcodeARMRegisters(bool from_scratch);
+ void HardcodeARMRegisters(bool from_scratch);
};
-class GDBRemoteRegisterContext : public RegisterContext
-{
+class GDBRemoteRegisterContext : public RegisterContext {
public:
- GDBRemoteRegisterContext (ThreadGDBRemote &thread,
- uint32_t concrete_frame_idx,
- GDBRemoteDynamicRegisterInfo &reg_info,
- bool read_all_at_once);
+ GDBRemoteRegisterContext(ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
+ GDBRemoteDynamicRegisterInfo &reg_info,
+ bool read_all_at_once);
+
+ ~GDBRemoteRegisterContext() override;
- ~GDBRemoteRegisterContext() override;
+ void InvalidateAllRegisters() override;
- void
- InvalidateAllRegisters () override;
+ size_t GetRegisterCount() override;
- size_t
- GetRegisterCount () override;
+ const RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
- const RegisterInfo *
- GetRegisterInfoAtIndex (size_t reg) override;
+ size_t GetRegisterSetCount() override;
- size_t
- GetRegisterSetCount () override;
+ const RegisterSet *GetRegisterSet(size_t reg_set) override;
- const RegisterSet *
- GetRegisterSet (size_t reg_set) override;
+ bool ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &value) override;
- bool
- ReadRegister (const RegisterInfo *reg_info, RegisterValue &value) override;
+ bool WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &value) override;
- bool
- WriteRegister (const RegisterInfo *reg_info, const RegisterValue &value) override;
-
- bool
- ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override;
+ bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
- bool
- WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override;
+ bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
- bool
- ReadAllRegisterValues (RegisterCheckpoint &reg_checkpoint) override;
+ bool ReadAllRegisterValues(RegisterCheckpoint &reg_checkpoint) override;
- bool
- WriteAllRegisterValues (const RegisterCheckpoint &reg_checkpoint) override;
+ bool
+ WriteAllRegisterValues(const RegisterCheckpoint &reg_checkpoint) override;
- uint32_t
- ConvertRegisterKindToRegisterNumber (lldb::RegisterKind kind, uint32_t num) override;
+ uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+ uint32_t num) override;
protected:
- friend class ThreadGDBRemote;
-
- bool
- ReadRegisterBytes (const RegisterInfo *reg_info,
- DataExtractor &data);
-
- bool
- WriteRegisterBytes (const RegisterInfo *reg_info,
- DataExtractor &data,
- uint32_t data_offset);
-
- bool
- PrivateSetRegisterValue (uint32_t reg, StringExtractor &response);
-
- bool
- PrivateSetRegisterValue (uint32_t reg, uint64_t val);
-
- void
- SetAllRegisterValid (bool b);
-
- bool
- GetRegisterIsValid (uint32_t reg) const
- {
-#if defined (LLDB_CONFIGURATION_DEBUG)
- assert (reg < m_reg_valid.size());
+ friend class ThreadGDBRemote;
+
+ bool ReadRegisterBytes(const RegisterInfo *reg_info, DataExtractor &data);
+
+ bool WriteRegisterBytes(const RegisterInfo *reg_info, DataExtractor &data,
+ uint32_t data_offset);
+
+ bool PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data);
+
+ bool PrivateSetRegisterValue(uint32_t reg, uint64_t val);
+
+ void SetAllRegisterValid(bool b);
+
+ bool GetRegisterIsValid(uint32_t reg) const {
+#if defined(LLDB_CONFIGURATION_DEBUG)
+ assert(reg < m_reg_valid.size());
#endif
- if (reg < m_reg_valid.size())
- return m_reg_valid[reg];
- return false;
- }
-
- void
- SetRegisterIsValid (const RegisterInfo *reg_info, bool valid)
- {
- if (reg_info)
- return SetRegisterIsValid (reg_info->kinds[lldb::eRegisterKindLLDB], valid);
- }
-
- void
- SetRegisterIsValid (uint32_t reg, bool valid)
- {
-#if defined (LLDB_CONFIGURATION_DEBUG)
- assert (reg < m_reg_valid.size());
+ if (reg < m_reg_valid.size())
+ return m_reg_valid[reg];
+ return false;
+ }
+
+ void SetRegisterIsValid(const RegisterInfo *reg_info, bool valid) {
+ if (reg_info)
+ return SetRegisterIsValid(reg_info->kinds[lldb::eRegisterKindLLDB],
+ valid);
+ }
+
+ void SetRegisterIsValid(uint32_t reg, bool valid) {
+#if defined(LLDB_CONFIGURATION_DEBUG)
+ assert(reg < m_reg_valid.size());
#endif
- if (reg < m_reg_valid.size())
- m_reg_valid[reg] = valid;
- }
-
- void
- SyncThreadState(Process *process); // Assumes the sequence mutex has already been acquired.
-
- GDBRemoteDynamicRegisterInfo &m_reg_info;
- std::vector<bool> m_reg_valid;
- DataExtractor m_reg_data;
- bool m_read_all_at_once;
+ if (reg < m_reg_valid.size())
+ m_reg_valid[reg] = valid;
+ }
+
+ GDBRemoteDynamicRegisterInfo &m_reg_info;
+ std::vector<bool> m_reg_valid;
+ DataExtractor m_reg_data;
+ bool m_read_all_at_once;
private:
- // Helper function for ReadRegisterBytes().
- bool GetPrimordialRegister(const RegisterInfo *reg_info,
- GDBRemoteCommunicationClient &gdb_comm);
- // Helper function for WriteRegisterBytes().
- bool SetPrimordialRegister(const RegisterInfo *reg_info,
- GDBRemoteCommunicationClient &gdb_comm);
-
- DISALLOW_COPY_AND_ASSIGN (GDBRemoteRegisterContext);
+ // Helper function for ReadRegisterBytes().
+ bool GetPrimordialRegister(const RegisterInfo *reg_info,
+ GDBRemoteCommunicationClient &gdb_comm);
+ // Helper function for WriteRegisterBytes().
+ bool SetPrimordialRegister(const RegisterInfo *reg_info,
+ GDBRemoteCommunicationClient &gdb_comm);
+
+ DISALLOW_COPY_AND_ASSIGN(GDBRemoteRegisterContext);
};
} // namespace process_gdb_remote
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index f53d4c6..4b4d62d 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -14,7 +14,8 @@
#include <stdlib.h>
#ifndef LLDB_DISABLE_POSIX
#include <netinet/in.h>
-#include <sys/mman.h> // for mmap
+#include <sys/mman.h> // for mmap
+#include <sys/socket.h>
#endif
#include <sys/stat.h>
#include <sys/types.h>
@@ -24,13 +25,11 @@
#include <algorithm>
#include <map>
#include <mutex>
+#include <sstream>
#include "lldb/Breakpoint/Watchpoint.h"
-#include "lldb/Interpreter/Args.h"
#include "lldb/Core/ArchSpec.h"
#include "lldb/Core/Debugger.h"
-#include "lldb/Host/ConnectionFileDescriptor.h"
-#include "lldb/Host/FileSpec.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/PluginManager.h"
@@ -40,136 +39,119 @@
#include "lldb/Core/Timer.h"
#include "lldb/Core/Value.h"
#include "lldb/DataFormatters/FormatManager.h"
+#include "lldb/Host/ConnectionFileDescriptor.h"
+#include "lldb/Host/FileSpec.h"
#include "lldb/Host/FileSystem.h"
#include "lldb/Host/HostThread.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/Symbols.h"
#include "lldb/Host/ThreadLauncher.h"
-#include "lldb/Host/TimeValue.h"
#include "lldb/Host/XML.h"
+#include "lldb/Interpreter/Args.h"
#include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandObject.h"
#include "lldb/Interpreter/CommandObjectMultiword.h"
#include "lldb/Interpreter/CommandReturnObject.h"
-#include "lldb/Interpreter/OptionValueProperties.h"
-#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/OptionGroupBoolean.h"
#include "lldb/Interpreter/OptionGroupUInt64.h"
+#include "lldb/Interpreter/OptionValueProperties.h"
+#include "lldb/Interpreter/Options.h"
#include "lldb/Interpreter/Property.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/DynamicLoader.h"
+#include "lldb/Target/SystemRuntime.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/TargetList.h"
#include "lldb/Target/ThreadPlanCallFunction.h"
-#include "lldb/Target/SystemRuntime.h"
+#include "lldb/Utility/CleanUp.h"
#include "lldb/Utility/PseudoTerminal.h"
// Project includes
-#include "lldb/Host/Host.h"
+#include "GDBRemoteRegisterContext.h"
+//#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
#include "Plugins/Process/Utility/GDBRemoteSignals.h"
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
#include "Plugins/Process/Utility/StopInfoMachException.h"
-//#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
-#include "Utility/StringExtractorGDBRemote.h"
-#include "GDBRemoteRegisterContext.h"
#include "ProcessGDBRemote.h"
#include "ProcessGDBRemoteLog.h"
#include "ThreadGDBRemote.h"
+#include "Utility/StringExtractorGDBRemote.h"
+#include "lldb/Host/Host.h"
-#define DEBUGSERVER_BASENAME "debugserver"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/raw_ostream.h"
+
+#define DEBUGSERVER_BASENAME "debugserver"
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
-namespace lldb
-{
- // Provide a function that can easily dump the packet history if we know a
- // ProcessGDBRemote * value (which we can get from logs or from debugging).
- // We need the function in the lldb namespace so it makes it into the final
- // executable since the LLDB shared library only exports stuff in the lldb
- // namespace. This allows you to attach with a debugger and call this
- // function and get the packet history dumped to a file.
- void
- DumpProcessGDBRemotePacketHistory (void *p, const char *path)
- {
- StreamFile strm;
- Error error (strm.GetFile().Open(path, File::eOpenOptionWrite | File::eOpenOptionCanCreate));
- if (error.Success())
- ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory (strm);
- }
+namespace lldb {
+// Provide a function that can easily dump the packet history if we know a
+// ProcessGDBRemote * value (which we can get from logs or from debugging).
+// We need the function in the lldb namespace so it makes it into the final
+// executable since the LLDB shared library only exports stuff in the lldb
+// namespace. This allows you to attach with a debugger and call this
+// function and get the packet history dumped to a file.
+void DumpProcessGDBRemotePacketHistory(void *p, const char *path) {
+ StreamFile strm;
+ Error error(strm.GetFile().Open(path, File::eOpenOptionWrite |
+ File::eOpenOptionCanCreate));
+ if (error.Success())
+ ((ProcessGDBRemote *)p)->GetGDBRemote().DumpHistory(strm);
+}
}
namespace {
- static PropertyDefinition
- g_properties[] =
- {
- { "packet-timeout" , OptionValue::eTypeUInt64 , true , 1, NULL, NULL, "Specify the default packet timeout in seconds." },
- { "target-definition-file" , OptionValue::eTypeFileSpec , true, 0 , NULL, NULL, "The file that provides the description for remote target registers." },
- { NULL , OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL }
- };
-
- enum
- {
- ePropertyPacketTimeout,
- ePropertyTargetDefinitionFile
- };
+static PropertyDefinition g_properties[] = {
+ {"packet-timeout", OptionValue::eTypeUInt64, true, 1, NULL, NULL,
+ "Specify the default packet timeout in seconds."},
+ {"target-definition-file", OptionValue::eTypeFileSpec, true, 0, NULL, NULL,
+ "The file that provides the description for remote target registers."},
+ {NULL, OptionValue::eTypeInvalid, false, 0, NULL, NULL, NULL}};
- class PluginProperties : public Properties
- {
- public:
-
- static ConstString
- GetSettingName ()
- {
- return ProcessGDBRemote::GetPluginNameStatic();
- }
-
- PluginProperties() :
- Properties ()
- {
- m_collection_sp.reset (new OptionValueProperties(GetSettingName()));
- m_collection_sp->Initialize(g_properties);
- }
-
- virtual
- ~PluginProperties()
- {
- }
-
- uint64_t
- GetPacketTimeout()
- {
- const uint32_t idx = ePropertyPacketTimeout;
- return m_collection_sp->GetPropertyAtIndexAsUInt64(NULL, idx, g_properties[idx].default_uint_value);
- }
-
- bool
- SetPacketTimeout(uint64_t timeout)
- {
- const uint32_t idx = ePropertyPacketTimeout;
- return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout);
- }
+enum { ePropertyPacketTimeout, ePropertyTargetDefinitionFile };
- FileSpec
- GetTargetDefinitionFile () const
- {
- const uint32_t idx = ePropertyTargetDefinitionFile;
- return m_collection_sp->GetPropertyAtIndexAsFileSpec (NULL, idx);
- }
- };
+class PluginProperties : public Properties {
+public:
+ static ConstString GetSettingName() {
+ return ProcessGDBRemote::GetPluginNameStatic();
+ }
+
+ PluginProperties() : Properties() {
+ m_collection_sp.reset(new OptionValueProperties(GetSettingName()));
+ m_collection_sp->Initialize(g_properties);
+ }
+
+ virtual ~PluginProperties() {}
+
+ uint64_t GetPacketTimeout() {
+ const uint32_t idx = ePropertyPacketTimeout;
+ return m_collection_sp->GetPropertyAtIndexAsUInt64(
+ NULL, idx, g_properties[idx].default_uint_value);
+ }
+
+ bool SetPacketTimeout(uint64_t timeout) {
+ const uint32_t idx = ePropertyPacketTimeout;
+ return m_collection_sp->SetPropertyAtIndexAsUInt64(NULL, idx, timeout);
+ }
+
+ FileSpec GetTargetDefinitionFile() const {
+ const uint32_t idx = ePropertyTargetDefinitionFile;
+ return m_collection_sp->GetPropertyAtIndexAsFileSpec(NULL, idx);
+ }
+};
- typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
+typedef std::shared_ptr<PluginProperties> ProcessKDPPropertiesSP;
- static const ProcessKDPPropertiesSP &
- GetGlobalPluginProperties()
- {
- static ProcessKDPPropertiesSP g_settings_sp;
- if (!g_settings_sp)
- g_settings_sp.reset (new PluginProperties ());
- return g_settings_sp;
- }
+static const ProcessKDPPropertiesSP &GetGlobalPluginProperties() {
+ static ProcessKDPPropertiesSP g_settings_sp;
+ if (!g_settings_sp)
+ g_settings_sp.reset(new PluginProperties());
+ return g_settings_sp;
+}
} // anonymous namespace end
@@ -177,3887 +159,3564 @@ namespace {
// ephemeral port from the kernel and make sure we reserve it before passing
// it to debugserver.
-#if defined (__APPLE__)
-#define LOW_PORT (IPPORT_RESERVED)
-#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
+#if defined(__APPLE__)
+#define LOW_PORT (IPPORT_RESERVED)
+#define HIGH_PORT (IPPORT_HIFIRSTAUTO)
#else
-#define LOW_PORT (1024u)
-#define HIGH_PORT (49151u)
+#define LOW_PORT (1024u)
+#define HIGH_PORT (49151u)
#endif
-#if defined(__APPLE__) && (defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
+#if defined(__APPLE__) && \
+ (defined(__arm__) || defined(__arm64__) || defined(__aarch64__))
static bool rand_initialized = false;
-static inline uint16_t
-get_random_port ()
-{
- if (!rand_initialized)
- {
- time_t seed = time(NULL);
+static inline uint16_t get_random_port() {
+ if (!rand_initialized) {
+ time_t seed = time(NULL);
- rand_initialized = true;
- srand(seed);
- }
- return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT;
+ rand_initialized = true;
+ srand(seed);
+ }
+ return (rand() % (HIGH_PORT - LOW_PORT)) + LOW_PORT;
}
#endif
-ConstString
-ProcessGDBRemote::GetPluginNameStatic()
-{
- static ConstString g_name("gdb-remote");
- return g_name;
+ConstString ProcessGDBRemote::GetPluginNameStatic() {
+ static ConstString g_name("gdb-remote");
+ return g_name;
}
-const char *
-ProcessGDBRemote::GetPluginDescriptionStatic()
-{
- return "GDB Remote protocol based debugging plug-in.";
+const char *ProcessGDBRemote::GetPluginDescriptionStatic() {
+ return "GDB Remote protocol based debugging plug-in.";
}
-void
-ProcessGDBRemote::Terminate()
-{
- PluginManager::UnregisterPlugin (ProcessGDBRemote::CreateInstance);
+void ProcessGDBRemote::Terminate() {
+ PluginManager::UnregisterPlugin(ProcessGDBRemote::CreateInstance);
}
-
lldb::ProcessSP
-ProcessGDBRemote::CreateInstance (lldb::TargetSP target_sp, ListenerSP listener_sp, const FileSpec *crash_file_path)
-{
- lldb::ProcessSP process_sp;
- if (crash_file_path == NULL)
- process_sp.reset (new ProcessGDBRemote (target_sp, listener_sp));
- return process_sp;
+ProcessGDBRemote::CreateInstance(lldb::TargetSP target_sp,
+ ListenerSP listener_sp,
+ const FileSpec *crash_file_path) {
+ lldb::ProcessSP process_sp;
+ if (crash_file_path == NULL)
+ process_sp.reset(new ProcessGDBRemote(target_sp, listener_sp));
+ return process_sp;
}
-bool
-ProcessGDBRemote::CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name)
-{
- if (plugin_specified_by_name)
- return true;
-
- // For now we are just making sure the file exists for a given module
- Module *exe_module = target_sp->GetExecutableModulePointer();
- if (exe_module)
- {
- ObjectFile *exe_objfile = exe_module->GetObjectFile();
- // We can't debug core files...
- switch (exe_objfile->GetType())
- {
- case ObjectFile::eTypeInvalid:
- case ObjectFile::eTypeCoreFile:
- case ObjectFile::eTypeDebugInfo:
- case ObjectFile::eTypeObjectFile:
- case ObjectFile::eTypeSharedLibrary:
- case ObjectFile::eTypeStubLibrary:
- case ObjectFile::eTypeJIT:
- return false;
- case ObjectFile::eTypeExecutable:
- case ObjectFile::eTypeDynamicLinker:
- case ObjectFile::eTypeUnknown:
- break;
- }
- return exe_module->GetFileSpec().Exists();
- }
- // However, if there is no executable module, we return true since we might be preparing to attach.
+bool ProcessGDBRemote::CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) {
+ if (plugin_specified_by_name)
return true;
+
+ // For now we are just making sure the file exists for a given module
+ Module *exe_module = target_sp->GetExecutableModulePointer();
+ if (exe_module) {
+ ObjectFile *exe_objfile = exe_module->GetObjectFile();
+ // We can't debug core files...
+ switch (exe_objfile->GetType()) {
+ case ObjectFile::eTypeInvalid:
+ case ObjectFile::eTypeCoreFile:
+ case ObjectFile::eTypeDebugInfo:
+ case ObjectFile::eTypeObjectFile:
+ case ObjectFile::eTypeSharedLibrary:
+ case ObjectFile::eTypeStubLibrary:
+ case ObjectFile::eTypeJIT:
+ return false;
+ case ObjectFile::eTypeExecutable:
+ case ObjectFile::eTypeDynamicLinker:
+ case ObjectFile::eTypeUnknown:
+ break;
+ }
+ return exe_module->GetFileSpec().Exists();
+ }
+ // However, if there is no executable module, we return true since we might be
+ // preparing to attach.
+ return true;
}
//----------------------------------------------------------------------
// ProcessGDBRemote constructor
//----------------------------------------------------------------------
-ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp, ListenerSP listener_sp)
- : Process(target_sp, listener_sp),
- m_flags(0),
- m_gdb_comm(),
- m_debugserver_pid(LLDB_INVALID_PROCESS_ID),
- m_last_stop_packet_mutex(),
+ProcessGDBRemote::ProcessGDBRemote(lldb::TargetSP target_sp,
+ ListenerSP listener_sp)
+ : Process(target_sp, listener_sp), m_flags(0), m_gdb_comm(),
+ m_debugserver_pid(LLDB_INVALID_PROCESS_ID), m_last_stop_packet_mutex(),
m_register_info(),
m_async_broadcaster(NULL, "lldb.process.gdb-remote.async-broadcaster"),
- m_async_listener_sp(Listener::MakeListener("lldb.process.gdb-remote.async-listener")),
- m_async_thread_state_mutex(),
- m_thread_ids(),
- m_thread_pcs(),
- m_jstopinfo_sp(),
- m_jthreadsinfo_sp(),
- m_continue_c_tids(),
- m_continue_C_tids(),
- m_continue_s_tids(),
- m_continue_S_tids(),
- m_max_memory_size(0),
- m_remote_stub_max_memory_size(0),
- m_addr_to_mmap_size(),
- m_thread_create_bp_sp(),
- m_waiting_for_attach(false),
- m_destroy_tried_resuming(false),
- m_command_sp(),
- m_breakpoint_pc_offset(0),
- m_initial_tid(LLDB_INVALID_THREAD_ID)
-{
- m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
- m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue, "async thread continue");
- m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit, "async thread did exit");
-
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));
-
- const uint32_t async_event_mask = eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
-
- if (m_async_listener_sp->StartListeningForEvents(&m_async_broadcaster, async_event_mask) != async_event_mask)
- {
- if (log)
- log->Printf("ProcessGDBRemote::%s failed to listen for m_async_broadcaster events", __FUNCTION__);
- }
-
- const uint32_t gdb_event_mask =
- Communication::eBroadcastBitReadThreadDidExit | GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify;
- if (m_async_listener_sp->StartListeningForEvents(&m_gdb_comm, gdb_event_mask) != gdb_event_mask)
- {
- if (log)
- log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events", __FUNCTION__);
- }
-
- const uint64_t timeout_seconds = GetGlobalPluginProperties()->GetPacketTimeout();
- if (timeout_seconds > 0)
- m_gdb_comm.SetPacketTimeout(timeout_seconds);
+ m_async_listener_sp(
+ Listener::MakeListener("lldb.process.gdb-remote.async-listener")),
+ m_async_thread_state_mutex(), m_thread_ids(), m_thread_pcs(),
+ m_jstopinfo_sp(), m_jthreadsinfo_sp(), m_continue_c_tids(),
+ m_continue_C_tids(), m_continue_s_tids(), m_continue_S_tids(),
+ m_max_memory_size(0), m_remote_stub_max_memory_size(0),
+ m_addr_to_mmap_size(), m_thread_create_bp_sp(),
+ m_waiting_for_attach(false), m_destroy_tried_resuming(false),
+ m_command_sp(), m_breakpoint_pc_offset(0),
+ m_initial_tid(LLDB_INVALID_THREAD_ID) {
+ m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadShouldExit,
+ "async thread should exit");
+ m_async_broadcaster.SetEventName(eBroadcastBitAsyncContinue,
+ "async thread continue");
+ m_async_broadcaster.SetEventName(eBroadcastBitAsyncThreadDidExit,
+ "async thread did exit");
+
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_ASYNC));
+
+ const uint32_t async_event_mask =
+ eBroadcastBitAsyncContinue | eBroadcastBitAsyncThreadShouldExit;
+
+ if (m_async_listener_sp->StartListeningForEvents(
+ &m_async_broadcaster, async_event_mask) != async_event_mask) {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s failed to listen for "
+ "m_async_broadcaster events",
+ __FUNCTION__);
+ }
+
+ const uint32_t gdb_event_mask =
+ Communication::eBroadcastBitReadThreadDidExit |
+ GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify;
+ if (m_async_listener_sp->StartListeningForEvents(
+ &m_gdb_comm, gdb_event_mask) != gdb_event_mask) {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s failed to listen for m_gdb_comm events",
+ __FUNCTION__);
+ }
+
+ const uint64_t timeout_seconds =
+ GetGlobalPluginProperties()->GetPacketTimeout();
+ if (timeout_seconds > 0)
+ m_gdb_comm.SetPacketTimeout(std::chrono::seconds(timeout_seconds));
}
//----------------------------------------------------------------------
// Destructor
//----------------------------------------------------------------------
-ProcessGDBRemote::~ProcessGDBRemote()
-{
- // m_mach_process.UnregisterNotificationCallbacks (this);
- Clear();
- // We need to call finalize on the process before destroying ourselves
- // to make sure all of the broadcaster cleanup goes as planned. If we
- // destruct this class, then Process::~Process() might have problems
- // trying to fully destroy the broadcaster.
- Finalize();
-
- // The general Finalize is going to try to destroy the process and that SHOULD
- // shut down the async thread. However, if we don't kill it it will get stranded and
- // its connection will go away so when it wakes up it will crash. So kill it for sure here.
- StopAsyncThread();
- KillDebugserverProcess();
+ProcessGDBRemote::~ProcessGDBRemote() {
+ // m_mach_process.UnregisterNotificationCallbacks (this);
+ Clear();
+ // We need to call finalize on the process before destroying ourselves
+ // to make sure all of the broadcaster cleanup goes as planned. If we
+ // destruct this class, then Process::~Process() might have problems
+ // trying to fully destroy the broadcaster.
+ Finalize();
+
+ // The general Finalize is going to try to destroy the process and that SHOULD
+ // shut down the async thread. However, if we don't kill it it will get
+ // stranded and
+ // its connection will go away so when it wakes up it will crash. So kill it
+ // for sure here.
+ StopAsyncThread();
+ KillDebugserverProcess();
}
//----------------------------------------------------------------------
// PluginInterface
//----------------------------------------------------------------------
-ConstString
-ProcessGDBRemote::GetPluginName()
-{
- return GetPluginNameStatic();
-}
-
-uint32_t
-ProcessGDBRemote::GetPluginVersion()
-{
- return 1;
-}
-
-bool
-ProcessGDBRemote::ParsePythonTargetDefinition(const FileSpec &target_definition_fspec)
-{
- ScriptInterpreter *interpreter = GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
- Error error;
- StructuredData::ObjectSP module_object_sp(interpreter->LoadPluginModule(target_definition_fspec, error));
- if (module_object_sp)
- {
- StructuredData::DictionarySP target_definition_sp(
- interpreter->GetDynamicSettings(module_object_sp, &GetTarget(), "gdb-server-target-definition", error));
-
- if (target_definition_sp)
- {
- StructuredData::ObjectSP target_object(target_definition_sp->GetValueForKey("host-info"));
- if (target_object)
- {
- if (auto host_info_dict = target_object->GetAsDictionary())
- {
- StructuredData::ObjectSP triple_value = host_info_dict->GetValueForKey("triple");
- if (auto triple_string_value = triple_value->GetAsString())
- {
- std::string triple_string = triple_string_value->GetValue();
- ArchSpec host_arch(triple_string.c_str());
- if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture()))
- {
- GetTarget().SetArchitecture(host_arch);
- }
- }
- }
- }
- m_breakpoint_pc_offset = 0;
- StructuredData::ObjectSP breakpoint_pc_offset_value = target_definition_sp->GetValueForKey("breakpoint-pc-offset");
- if (breakpoint_pc_offset_value)
- {
- if (auto breakpoint_pc_int_value = breakpoint_pc_offset_value->GetAsInteger())
- m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue();
- }
-
- if (m_register_info.SetRegisterInfo(*target_definition_sp, GetTarget().GetArchitecture()) > 0)
- {
- return true;
+ConstString ProcessGDBRemote::GetPluginName() { return GetPluginNameStatic(); }
+
+uint32_t ProcessGDBRemote::GetPluginVersion() { return 1; }
+
+bool ProcessGDBRemote::ParsePythonTargetDefinition(
+ const FileSpec &target_definition_fspec) {
+ ScriptInterpreter *interpreter =
+ GetTarget().GetDebugger().GetCommandInterpreter().GetScriptInterpreter();
+ Error error;
+ StructuredData::ObjectSP module_object_sp(
+ interpreter->LoadPluginModule(target_definition_fspec, error));
+ if (module_object_sp) {
+ StructuredData::DictionarySP target_definition_sp(
+ interpreter->GetDynamicSettings(module_object_sp, &GetTarget(),
+ "gdb-server-target-definition", error));
+
+ if (target_definition_sp) {
+ StructuredData::ObjectSP target_object(
+ target_definition_sp->GetValueForKey("host-info"));
+ if (target_object) {
+ if (auto host_info_dict = target_object->GetAsDictionary()) {
+ StructuredData::ObjectSP triple_value =
+ host_info_dict->GetValueForKey("triple");
+ if (auto triple_string_value = triple_value->GetAsString()) {
+ std::string triple_string = triple_string_value->GetValue();
+ ArchSpec host_arch(triple_string.c_str());
+ if (!host_arch.IsCompatibleMatch(GetTarget().GetArchitecture())) {
+ GetTarget().SetArchitecture(host_arch);
}
+ }
}
+ }
+ m_breakpoint_pc_offset = 0;
+ StructuredData::ObjectSP breakpoint_pc_offset_value =
+ target_definition_sp->GetValueForKey("breakpoint-pc-offset");
+ if (breakpoint_pc_offset_value) {
+ if (auto breakpoint_pc_int_value =
+ breakpoint_pc_offset_value->GetAsInteger())
+ m_breakpoint_pc_offset = breakpoint_pc_int_value->GetValue();
+ }
+
+ if (m_register_info.SetRegisterInfo(*target_definition_sp,
+ GetTarget().GetArchitecture()) > 0) {
+ return true;
+ }
}
- return false;
+ }
+ return false;
}
-// If the remote stub didn't give us eh_frame or DWARF register numbers for a register,
+// If the remote stub didn't give us eh_frame or DWARF register numbers for a
+// register,
// see if the ABI can provide them.
// DWARF and eh_frame register numbers are defined as a part of the ABI.
-static void
-AugmentRegisterInfoViaABI (RegisterInfo &reg_info, ConstString reg_name, ABISP abi_sp)
-{
- if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM
- || reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM)
- {
- if (abi_sp)
- {
- RegisterInfo abi_reg_info;
- if (abi_sp->GetRegisterInfoByName (reg_name, abi_reg_info))
- {
- if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM)
- {
- reg_info.kinds[eRegisterKindEHFrame] = abi_reg_info.kinds[eRegisterKindEHFrame];
- }
- if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM)
- {
- reg_info.kinds[eRegisterKindDWARF] = abi_reg_info.kinds[eRegisterKindDWARF];
- }
- if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM &&
- abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM)
- {
- reg_info.kinds[eRegisterKindGeneric] = abi_reg_info.kinds[eRegisterKindGeneric];
- }
- }
+static void AugmentRegisterInfoViaABI(RegisterInfo &reg_info,
+ ConstString reg_name, ABISP abi_sp) {
+ if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM ||
+ reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM) {
+ if (abi_sp) {
+ RegisterInfo abi_reg_info;
+ if (abi_sp->GetRegisterInfoByName(reg_name, abi_reg_info)) {
+ if (reg_info.kinds[eRegisterKindEHFrame] == LLDB_INVALID_REGNUM &&
+ abi_reg_info.kinds[eRegisterKindEHFrame] != LLDB_INVALID_REGNUM) {
+ reg_info.kinds[eRegisterKindEHFrame] =
+ abi_reg_info.kinds[eRegisterKindEHFrame];
}
- }
-}
-
-static size_t
-SplitCommaSeparatedRegisterNumberString(const llvm::StringRef &comma_separated_regiter_numbers, std::vector<uint32_t> &regnums, int base)
-{
- regnums.clear();
- std::pair<llvm::StringRef, llvm::StringRef> value_pair;
- value_pair.second = comma_separated_regiter_numbers;
- do
- {
- value_pair = value_pair.second.split(',');
- if (!value_pair.first.empty())
- {
- uint32_t reg = StringConvert::ToUInt32 (value_pair.first.str().c_str(), LLDB_INVALID_REGNUM, base);
- if (reg != LLDB_INVALID_REGNUM)
- regnums.push_back (reg);
- }
- } while (!value_pair.second.empty());
- return regnums.size();
-}
-
-
-void
-ProcessGDBRemote::BuildDynamicRegisterInfo (bool force)
-{
- if (!force && m_register_info.GetNumRegisters() > 0)
- return;
-
- m_register_info.Clear();
-
- // Check if qHostInfo specified a specific packet timeout for this connection.
- // If so then lets update our setting so the user knows what the timeout is
- // and can see it.
- const uint32_t host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
- if (host_packet_timeout)
- {
- GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout);
- }
-
- // Register info search order:
- // 1 - Use the target definition python file if one is specified.
- // 2 - If the target definition doesn't have any of the info from the target.xml (registers) then proceed to read the target.xml.
- // 3 - Fall back on the qRegisterInfo packets.
-
- FileSpec target_definition_fspec = GetGlobalPluginProperties()->GetTargetDefinitionFile ();
- if (!target_definition_fspec.Exists())
- {
- // If the filename doesn't exist, it may be a ~ not having been expanded - try to resolve it.
- target_definition_fspec.ResolvePath();
- }
- if (target_definition_fspec)
- {
- // See if we can get register definitions from a python file
- if (ParsePythonTargetDefinition (target_definition_fspec))
- {
- return;
+ if (reg_info.kinds[eRegisterKindDWARF] == LLDB_INVALID_REGNUM &&
+ abi_reg_info.kinds[eRegisterKindDWARF] != LLDB_INVALID_REGNUM) {
+ reg_info.kinds[eRegisterKindDWARF] =
+ abi_reg_info.kinds[eRegisterKindDWARF];
}
- else
- {
- StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
- stream_sp->Printf ("ERROR: target description file %s failed to parse.\n", target_definition_fspec.GetPath().c_str());
+ if (reg_info.kinds[eRegisterKindGeneric] == LLDB_INVALID_REGNUM &&
+ abi_reg_info.kinds[eRegisterKindGeneric] != LLDB_INVALID_REGNUM) {
+ reg_info.kinds[eRegisterKindGeneric] =
+ abi_reg_info.kinds[eRegisterKindGeneric];
}
+ }
}
+ }
+}
- const ArchSpec &target_arch = GetTarget().GetArchitecture();
- const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture();
- const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
+static size_t SplitCommaSeparatedRegisterNumberString(
+ const llvm::StringRef &comma_separated_regiter_numbers,
+ std::vector<uint32_t> &regnums, int base) {
+ regnums.clear();
+ std::pair<llvm::StringRef, llvm::StringRef> value_pair;
+ value_pair.second = comma_separated_regiter_numbers;
+ do {
+ value_pair = value_pair.second.split(',');
+ if (!value_pair.first.empty()) {
+ uint32_t reg = StringConvert::ToUInt32(value_pair.first.str().c_str(),
+ LLDB_INVALID_REGNUM, base);
+ if (reg != LLDB_INVALID_REGNUM)
+ regnums.push_back(reg);
+ }
+ } while (!value_pair.second.empty());
+ return regnums.size();
+}
- // Use the process' architecture instead of the host arch, if available
- ArchSpec arch_to_use;
- if (remote_process_arch.IsValid ())
- arch_to_use = remote_process_arch;
- else
- arch_to_use = remote_host_arch;
-
- if (!arch_to_use.IsValid())
- arch_to_use = target_arch;
-
- if (GetGDBServerRegisterInfo (arch_to_use))
- return;
-
- char packet[128];
- uint32_t reg_offset = 0;
- uint32_t reg_num = 0;
- for (StringExtractorGDBRemote::ResponseType response_type = StringExtractorGDBRemote::eResponse;
- response_type == StringExtractorGDBRemote::eResponse;
- ++reg_num)
- {
- const int packet_len = ::snprintf (packet, sizeof(packet), "qRegisterInfo%x", reg_num);
- assert (packet_len < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, false) == GDBRemoteCommunication::PacketResult::Success)
- {
- response_type = response.GetResponseType();
- if (response_type == StringExtractorGDBRemote::eResponse)
+void ProcessGDBRemote::BuildDynamicRegisterInfo(bool force) {
+ if (!force && m_register_info.GetNumRegisters() > 0)
+ return;
+
+ m_register_info.Clear();
+
+ // Check if qHostInfo specified a specific packet timeout for this connection.
+ // If so then lets update our setting so the user knows what the timeout is
+ // and can see it.
+ const auto host_packet_timeout = m_gdb_comm.GetHostDefaultPacketTimeout();
+ if (host_packet_timeout > std::chrono::seconds(0)) {
+ GetGlobalPluginProperties()->SetPacketTimeout(host_packet_timeout.count());
+ }
+
+ // Register info search order:
+ // 1 - Use the target definition python file if one is specified.
+ // 2 - If the target definition doesn't have any of the info from the
+ // target.xml (registers) then proceed to read the target.xml.
+ // 3 - Fall back on the qRegisterInfo packets.
+
+ FileSpec target_definition_fspec =
+ GetGlobalPluginProperties()->GetTargetDefinitionFile();
+ if (!target_definition_fspec.Exists()) {
+ // If the filename doesn't exist, it may be a ~ not having been expanded -
+ // try to resolve it.
+ target_definition_fspec.ResolvePath();
+ }
+ if (target_definition_fspec) {
+ // See if we can get register definitions from a python file
+ if (ParsePythonTargetDefinition(target_definition_fspec)) {
+ return;
+ } else {
+ StreamSP stream_sp = GetTarget().GetDebugger().GetAsyncOutputStream();
+ stream_sp->Printf("ERROR: target description file %s failed to parse.\n",
+ target_definition_fspec.GetPath().c_str());
+ }
+ }
+
+ const ArchSpec &target_arch = GetTarget().GetArchitecture();
+ const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture();
+ const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
+
+ // Use the process' architecture instead of the host arch, if available
+ ArchSpec arch_to_use;
+ if (remote_process_arch.IsValid())
+ arch_to_use = remote_process_arch;
+ else
+ arch_to_use = remote_host_arch;
+
+ if (!arch_to_use.IsValid())
+ arch_to_use = target_arch;
+
+ if (GetGDBServerRegisterInfo(arch_to_use))
+ return;
+
+ char packet[128];
+ uint32_t reg_offset = 0;
+ uint32_t reg_num = 0;
+ for (StringExtractorGDBRemote::ResponseType response_type =
+ StringExtractorGDBRemote::eResponse;
+ response_type == StringExtractorGDBRemote::eResponse; ++reg_num) {
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "qRegisterInfo%x", reg_num);
+ assert(packet_len < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, false) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ response_type = response.GetResponseType();
+ if (response_type == StringExtractorGDBRemote::eResponse) {
+ llvm::StringRef name;
+ llvm::StringRef value;
+ ConstString reg_name;
+ ConstString alt_name;
+ ConstString set_name;
+ std::vector<uint32_t> value_regs;
+ std::vector<uint32_t> invalidate_regs;
+ std::vector<uint8_t> dwarf_opcode_bytes;
+ RegisterInfo reg_info = {
+ NULL, // Name
+ NULL, // Alt name
+ 0, // byte size
+ reg_offset, // offset
+ eEncodingUint, // encoding
+ eFormatHex, // format
{
- std::string name;
- std::string value;
- ConstString reg_name;
- ConstString alt_name;
- ConstString set_name;
- std::vector<uint32_t> value_regs;
- std::vector<uint32_t> invalidate_regs;
- std::vector<uint8_t> dwarf_opcode_bytes;
- RegisterInfo reg_info = { NULL, // Name
- NULL, // Alt name
- 0, // byte size
- reg_offset, // offset
- eEncodingUint, // encoding
- eFormatHex, // format
- {
- LLDB_INVALID_REGNUM, // eh_frame reg num
- LLDB_INVALID_REGNUM, // DWARF reg num
- LLDB_INVALID_REGNUM, // generic reg num
- reg_num, // process plugin reg num
- reg_num // native register number
- },
- NULL,
- NULL,
- NULL, // Dwarf expression opcode bytes pointer
- 0 // Dwarf expression opcode bytes length
- };
-
- while (response.GetNameColonValue(name, value))
- {
- if (name.compare("name") == 0)
- {
- reg_name.SetCString(value.c_str());
- }
- else if (name.compare("alt-name") == 0)
- {
- alt_name.SetCString(value.c_str());
- }
- else if (name.compare("bitsize") == 0)
- {
- reg_info.byte_size = StringConvert::ToUInt32(value.c_str(), 0, 0) / CHAR_BIT;
- }
- else if (name.compare("offset") == 0)
- {
- uint32_t offset = StringConvert::ToUInt32(value.c_str(), UINT32_MAX, 0);
- if (reg_offset != offset)
- {
- reg_offset = offset;
- }
- }
- else if (name.compare("encoding") == 0)
- {
- const Encoding encoding = Args::StringToEncoding (value.c_str());
- if (encoding != eEncodingInvalid)
- reg_info.encoding = encoding;
- }
- else if (name.compare("format") == 0)
- {
- Format format = eFormatInvalid;
- if (Args::StringToFormat (value.c_str(), format, NULL).Success())
- reg_info.format = format;
- else if (value.compare("binary") == 0)
- reg_info.format = eFormatBinary;
- else if (value.compare("decimal") == 0)
- reg_info.format = eFormatDecimal;
- else if (value.compare("hex") == 0)
- reg_info.format = eFormatHex;
- else if (value.compare("float") == 0)
- reg_info.format = eFormatFloat;
- else if (value.compare("vector-sint8") == 0)
- reg_info.format = eFormatVectorOfSInt8;
- else if (value.compare("vector-uint8") == 0)
- reg_info.format = eFormatVectorOfUInt8;
- else if (value.compare("vector-sint16") == 0)
- reg_info.format = eFormatVectorOfSInt16;
- else if (value.compare("vector-uint16") == 0)
- reg_info.format = eFormatVectorOfUInt16;
- else if (value.compare("vector-sint32") == 0)
- reg_info.format = eFormatVectorOfSInt32;
- else if (value.compare("vector-uint32") == 0)
- reg_info.format = eFormatVectorOfUInt32;
- else if (value.compare("vector-float32") == 0)
- reg_info.format = eFormatVectorOfFloat32;
- else if (value.compare("vector-uint128") == 0)
- reg_info.format = eFormatVectorOfUInt128;
- }
- else if (name.compare("set") == 0)
- {
- set_name.SetCString(value.c_str());
- }
- else if (name.compare("gcc") == 0 || name.compare("ehframe") == 0)
- {
- reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
- }
- else if (name.compare("dwarf") == 0)
- {
- reg_info.kinds[eRegisterKindDWARF] = StringConvert::ToUInt32(value.c_str(), LLDB_INVALID_REGNUM, 0);
- }
- else if (name.compare("generic") == 0)
- {
- reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister (value.c_str());
- }
- else if (name.compare("container-regs") == 0)
- {
- SplitCommaSeparatedRegisterNumberString(value, value_regs, 16);
- }
- else if (name.compare("invalidate-regs") == 0)
- {
- SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16);
- }
- else if (name.compare("dynamic_size_dwarf_expr_bytes") == 0)
- {
- size_t dwarf_opcode_len = value.length () / 2;
- assert (dwarf_opcode_len > 0);
-
- dwarf_opcode_bytes.resize (dwarf_opcode_len);
- StringExtractor opcode_extractor;
- reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
-
- // Swap "value" over into "opcode_extractor"
- opcode_extractor.GetStringRef ().swap (value);
- uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes.data (),
- dwarf_opcode_len);
- assert (dwarf_opcode_len == ret_val);
-
- reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data ();
- }
- }
-
- reg_info.byte_offset = reg_offset;
- assert (reg_info.byte_size != 0);
- reg_offset += reg_info.byte_size;
- if (!value_regs.empty())
- {
- value_regs.push_back(LLDB_INVALID_REGNUM);
- reg_info.value_regs = value_regs.data();
- }
- if (!invalidate_regs.empty())
- {
- invalidate_regs.push_back(LLDB_INVALID_REGNUM);
- reg_info.invalidate_regs = invalidate_regs.data();
- }
-
- // We have to make a temporary ABI here, and not use the GetABI because this code
- // gets called in DidAttach, when the target architecture (and consequently the ABI we'll get from
- // the process) may be wrong.
- ABISP abi_to_use = ABI::FindPlugin(arch_to_use);
-
- AugmentRegisterInfoViaABI (reg_info, reg_name, abi_to_use);
+ LLDB_INVALID_REGNUM, // eh_frame reg num
+ LLDB_INVALID_REGNUM, // DWARF reg num
+ LLDB_INVALID_REGNUM, // generic reg num
+ reg_num, // process plugin reg num
+ reg_num // native register number
+ },
+ NULL,
+ NULL,
+ NULL, // Dwarf expression opcode bytes pointer
+ 0 // Dwarf expression opcode bytes length
+ };
- m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
+ while (response.GetNameColonValue(name, value)) {
+ if (name.equals("name")) {
+ reg_name.SetString(value);
+ } else if (name.equals("alt-name")) {
+ alt_name.SetString(value);
+ } else if (name.equals("bitsize")) {
+ value.getAsInteger(0, reg_info.byte_size);
+ reg_info.byte_size /= CHAR_BIT;
+ } else if (name.equals("offset")) {
+ if (value.getAsInteger(0, reg_offset))
+ reg_offset = UINT32_MAX;
+ } else if (name.equals("encoding")) {
+ const Encoding encoding = Args::StringToEncoding(value);
+ if (encoding != eEncodingInvalid)
+ reg_info.encoding = encoding;
+ } else if (name.equals("format")) {
+ Format format = eFormatInvalid;
+ if (Args::StringToFormat(value.str().c_str(), format, NULL)
+ .Success())
+ reg_info.format = format;
+ else {
+ reg_info.format =
+ llvm::StringSwitch<Format>(value)
+ .Case("binary", eFormatBinary)
+ .Case("decimal", eFormatDecimal)
+ .Case("hex", eFormatHex)
+ .Case("float", eFormatFloat)
+ .Case("vector-sint8", eFormatVectorOfSInt8)
+ .Case("vector-uint8", eFormatVectorOfUInt8)
+ .Case("vector-sint16", eFormatVectorOfSInt16)
+ .Case("vector-uint16", eFormatVectorOfUInt16)
+ .Case("vector-sint32", eFormatVectorOfSInt32)
+ .Case("vector-uint32", eFormatVectorOfUInt32)
+ .Case("vector-float32", eFormatVectorOfFloat32)
+ .Case("vector-uint64", eFormatVectorOfUInt64)
+ .Case("vector-uint128", eFormatVectorOfUInt128)
+ .Default(eFormatInvalid);
}
- else
- {
- break; // ensure exit before reg_num is incremented
- }
- }
- else
- {
- break;
+ } else if (name.equals("set")) {
+ set_name.SetString(value);
+ } else if (name.equals("gcc") || name.equals("ehframe")) {
+ if (value.getAsInteger(0, reg_info.kinds[eRegisterKindEHFrame]))
+ reg_info.kinds[eRegisterKindEHFrame] = LLDB_INVALID_REGNUM;
+ } else if (name.equals("dwarf")) {
+ if (value.getAsInteger(0, reg_info.kinds[eRegisterKindDWARF]))
+ reg_info.kinds[eRegisterKindDWARF] = LLDB_INVALID_REGNUM;
+ } else if (name.equals("generic")) {
+ reg_info.kinds[eRegisterKindGeneric] =
+ Args::StringToGenericRegister(value);
+ } else if (name.equals("container-regs")) {
+ SplitCommaSeparatedRegisterNumberString(value, value_regs, 16);
+ } else if (name.equals("invalidate-regs")) {
+ SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 16);
+ } else if (name.equals("dynamic_size_dwarf_expr_bytes")) {
+ size_t dwarf_opcode_len = value.size() / 2;
+ assert(dwarf_opcode_len > 0);
+
+ dwarf_opcode_bytes.resize(dwarf_opcode_len);
+ reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
+
+ StringExtractor opcode_extractor(value);
+ uint32_t ret_val =
+ opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes);
+ assert(dwarf_opcode_len == ret_val);
+
+ reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data();
+ }
}
- }
- if (m_register_info.GetNumRegisters() > 0)
- {
- m_register_info.Finalize(GetTarget().GetArchitecture());
- return;
- }
+ reg_info.byte_offset = reg_offset;
+ assert(reg_info.byte_size != 0);
+ reg_offset += reg_info.byte_size;
+ if (!value_regs.empty()) {
+ value_regs.push_back(LLDB_INVALID_REGNUM);
+ reg_info.value_regs = value_regs.data();
+ }
+ if (!invalidate_regs.empty()) {
+ invalidate_regs.push_back(LLDB_INVALID_REGNUM);
+ reg_info.invalidate_regs = invalidate_regs.data();
+ }
- // We didn't get anything if the accumulated reg_num is zero. See if we are
- // debugging ARM and fill with a hard coded register set until we can get an
- // updated debugserver down on the devices.
- // On the other hand, if the accumulated reg_num is positive, see if we can
- // add composite registers to the existing primordial ones.
- bool from_scratch = (m_register_info.GetNumRegisters() == 0);
+ // We have to make a temporary ABI here, and not use the GetABI because
+ // this code
+ // gets called in DidAttach, when the target architecture (and
+ // consequently the ABI we'll get from
+ // the process) may be wrong.
+ ABISP abi_to_use = ABI::FindPlugin(arch_to_use);
- if (!target_arch.IsValid())
- {
- if (arch_to_use.IsValid()
- && (arch_to_use.GetMachine() == llvm::Triple::arm || arch_to_use.GetMachine() == llvm::Triple::thumb)
- && arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple)
- m_register_info.HardcodeARMRegisters(from_scratch);
- }
- else if (target_arch.GetMachine() == llvm::Triple::arm
- || target_arch.GetMachine() == llvm::Triple::thumb)
- {
- m_register_info.HardcodeARMRegisters(from_scratch);
- }
+ AugmentRegisterInfoViaABI(reg_info, reg_name, abi_to_use);
- // At this point, we can finalize our register info.
- m_register_info.Finalize (GetTarget().GetArchitecture());
+ m_register_info.AddRegister(reg_info, reg_name, alt_name, set_name);
+ } else {
+ break; // ensure exit before reg_num is incremented
+ }
+ } else {
+ break;
+ }
+ }
+
+ if (m_register_info.GetNumRegisters() > 0) {
+ m_register_info.Finalize(GetTarget().GetArchitecture());
+ return;
+ }
+
+ // We didn't get anything if the accumulated reg_num is zero. See if we are
+ // debugging ARM and fill with a hard coded register set until we can get an
+ // updated debugserver down on the devices.
+ // On the other hand, if the accumulated reg_num is positive, see if we can
+ // add composite registers to the existing primordial ones.
+ bool from_scratch = (m_register_info.GetNumRegisters() == 0);
+
+ if (!target_arch.IsValid()) {
+ if (arch_to_use.IsValid() &&
+ (arch_to_use.GetMachine() == llvm::Triple::arm ||
+ arch_to_use.GetMachine() == llvm::Triple::thumb) &&
+ arch_to_use.GetTriple().getVendor() == llvm::Triple::Apple)
+ m_register_info.HardcodeARMRegisters(from_scratch);
+ } else if (target_arch.GetMachine() == llvm::Triple::arm ||
+ target_arch.GetMachine() == llvm::Triple::thumb) {
+ m_register_info.HardcodeARMRegisters(from_scratch);
+ }
+
+ // At this point, we can finalize our register info.
+ m_register_info.Finalize(GetTarget().GetArchitecture());
}
-Error
-ProcessGDBRemote::WillLaunch (Module* module)
-{
- return WillLaunchOrAttach ();
+Error ProcessGDBRemote::WillLaunch(Module *module) {
+ return WillLaunchOrAttach();
}
-Error
-ProcessGDBRemote::WillAttachToProcessWithID (lldb::pid_t pid)
-{
- return WillLaunchOrAttach ();
+Error ProcessGDBRemote::WillAttachToProcessWithID(lldb::pid_t pid) {
+ return WillLaunchOrAttach();
}
-Error
-ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wait_for_launch)
-{
- return WillLaunchOrAttach ();
+Error ProcessGDBRemote::WillAttachToProcessWithName(const char *process_name,
+ bool wait_for_launch) {
+ return WillLaunchOrAttach();
}
-Error
-ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- Error error (WillLaunchOrAttach ());
-
- if (error.Fail())
- return error;
-
- error = ConnectToDebugserver (remote_url);
+Error ProcessGDBRemote::DoConnectRemote(Stream *strm,
+ llvm::StringRef remote_url) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ Error error(WillLaunchOrAttach());
- if (error.Fail())
- return error;
- StartAsyncThread ();
-
- lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
- if (pid == LLDB_INVALID_PROCESS_ID)
- {
- // We don't have a valid process ID, so note that we are connected
- // and could now request to launch or attach, or get remote process
- // listings...
- SetPrivateState (eStateConnected);
- }
- else
- {
- // We have a valid process
- SetID (pid);
- GetThreadList();
- StringExtractorGDBRemote response;
- if (m_gdb_comm.GetStopReply(response))
- {
- SetLastStopPacket(response);
+ if (error.Fail())
+ return error;
- // '?' Packets must be handled differently in non-stop mode
- if (GetTarget().GetNonStopModeEnabled())
- HandleStopReplySequence();
+ error = ConnectToDebugserver(remote_url);
- Target &target = GetTarget();
- if (!target.GetArchitecture().IsValid())
- {
- if (m_gdb_comm.GetProcessArchitecture().IsValid())
- {
- target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
- }
- else
- {
- target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
- }
- }
-
- const StateType state = SetThreadStopInfo (response);
- if (state != eStateInvalid)
- {
- SetPrivateState (state);
- }
- else
- error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but state was not stopped: %s", pid, remote_url, StateAsCString (state));
+ if (error.Fail())
+ return error;
+ StartAsyncThread();
+
+ lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
+ if (pid == LLDB_INVALID_PROCESS_ID) {
+ // We don't have a valid process ID, so note that we are connected
+ // and could now request to launch or attach, or get remote process
+ // listings...
+ SetPrivateState(eStateConnected);
+ } else {
+ // We have a valid process
+ SetID(pid);
+ GetThreadList();
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.GetStopReply(response)) {
+ SetLastStopPacket(response);
+
+ // '?' Packets must be handled differently in non-stop mode
+ if (GetTarget().GetNonStopModeEnabled())
+ HandleStopReplySequence();
+
+ Target &target = GetTarget();
+ if (!target.GetArchitecture().IsValid()) {
+ if (m_gdb_comm.GetProcessArchitecture().IsValid()) {
+ target.SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ } else {
+ target.SetArchitecture(m_gdb_comm.GetHostArchitecture());
}
- else
- error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url);
- }
-
- if (log)
- log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalizing target architecture initial triple: %s (GetTarget().GetArchitecture().IsValid() %s, m_gdb_comm.GetHostArchitecture().IsValid(): %s)", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str (), GetTarget ().GetArchitecture ().IsValid () ? "true" : "false", m_gdb_comm.GetHostArchitecture ().IsValid () ? "true" : "false");
-
-
- if (error.Success()
- && !GetTarget().GetArchitecture().IsValid()
- && m_gdb_comm.GetHostArchitecture().IsValid())
- {
- // Prefer the *process'* architecture over that of the *host*, if available.
- if (m_gdb_comm.GetProcessArchitecture().IsValid())
- GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture());
- else
- GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture());
- }
-
- if (log)
- log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalized target architecture triple: %s", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str ());
-
- if (error.Success())
- {
- PlatformSP platform_sp = GetTarget().GetPlatform();
- if (platform_sp && platform_sp->IsConnected())
- SetUnixSignals(platform_sp->GetUnixSignals());
- else
- SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture()));
- }
+ }
+
+ const StateType state = SetThreadStopInfo(response);
+ if (state != eStateInvalid) {
+ SetPrivateState(state);
+ } else
+ error.SetErrorStringWithFormat(
+ "Process %" PRIu64 " was reported after connecting to "
+ "'%s', but state was not stopped: %s",
+ pid, remote_url.str().c_str(), StateAsCString(state));
+ } else
+ error.SetErrorStringWithFormat("Process %" PRIu64
+ " was reported after connecting to '%s', "
+ "but no stop reply packet was received",
+ pid, remote_url.str().c_str());
+ }
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s pid %" PRIu64
+ ": normalizing target architecture initial triple: %s "
+ "(GetTarget().GetArchitecture().IsValid() %s, "
+ "m_gdb_comm.GetHostArchitecture().IsValid(): %s)",
+ __FUNCTION__, GetID(),
+ GetTarget().GetArchitecture().GetTriple().getTriple().c_str(),
+ GetTarget().GetArchitecture().IsValid() ? "true" : "false",
+ m_gdb_comm.GetHostArchitecture().IsValid() ? "true" : "false");
+
+ if (error.Success() && !GetTarget().GetArchitecture().IsValid() &&
+ m_gdb_comm.GetHostArchitecture().IsValid()) {
+ // Prefer the *process'* architecture over that of the *host*, if available.
+ if (m_gdb_comm.GetProcessArchitecture().IsValid())
+ GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture());
+ else
+ GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture());
+ }
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s pid %" PRIu64
+ ": normalized target architecture triple: %s",
+ __FUNCTION__, GetID(),
+ GetTarget().GetArchitecture().GetTriple().getTriple().c_str());
+
+ if (error.Success()) {
+ PlatformSP platform_sp = GetTarget().GetPlatform();
+ if (platform_sp && platform_sp->IsConnected())
+ SetUnixSignals(platform_sp->GetUnixSignals());
+ else
+ SetUnixSignals(UnixSignals::Create(GetTarget().GetArchitecture()));
+ }
- return error;
+ return error;
}
-Error
-ProcessGDBRemote::WillLaunchOrAttach ()
-{
- Error error;
- m_stdio_communication.Clear ();
- return error;
+Error ProcessGDBRemote::WillLaunchOrAttach() {
+ Error error;
+ m_stdio_communication.Clear();
+ return error;
}
//----------------------------------------------------------------------
// Process Control
//----------------------------------------------------------------------
-Error
-ProcessGDBRemote::DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- Error error;
-
- if (log)
- log->Printf ("ProcessGDBRemote::%s() entered", __FUNCTION__);
-
- uint32_t launch_flags = launch_info.GetFlags().Get();
- FileSpec stdin_file_spec{};
- FileSpec stdout_file_spec{};
- FileSpec stderr_file_spec{};
- FileSpec working_dir = launch_info.GetWorkingDirectory();
-
- const FileAction *file_action;
- file_action = launch_info.GetFileActionForFD (STDIN_FILENO);
- if (file_action)
- {
- if (file_action->GetAction() == FileAction::eFileActionOpen)
- stdin_file_spec = file_action->GetFileSpec();
- }
- file_action = launch_info.GetFileActionForFD (STDOUT_FILENO);
- if (file_action)
- {
- if (file_action->GetAction() == FileAction::eFileActionOpen)
- stdout_file_spec = file_action->GetFileSpec();
- }
- file_action = launch_info.GetFileActionForFD (STDERR_FILENO);
- if (file_action)
- {
- if (file_action->GetAction() == FileAction::eFileActionOpen)
- stderr_file_spec = file_action->GetFileSpec();
- }
-
- if (log)
- {
- if (stdin_file_spec || stdout_file_spec || stderr_file_spec)
- log->Printf ("ProcessGDBRemote::%s provided with STDIO paths via launch_info: stdin=%s, stdout=%s, stderr=%s",
- __FUNCTION__,
- stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
- stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
- stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
- else
- log->Printf ("ProcessGDBRemote::%s no STDIO paths given via launch_info", __FUNCTION__);
- }
-
- const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
- if (stdin_file_spec || disable_stdio)
- {
- // the inferior will be reading stdin from the specified file
- // or stdio is completely disabled
- m_stdin_forward = false;
- }
+Error ProcessGDBRemote::DoLaunch(Module *exe_module,
+ ProcessLaunchInfo &launch_info) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ Error error;
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s() entered", __FUNCTION__);
+
+ uint32_t launch_flags = launch_info.GetFlags().Get();
+ FileSpec stdin_file_spec{};
+ FileSpec stdout_file_spec{};
+ FileSpec stderr_file_spec{};
+ FileSpec working_dir = launch_info.GetWorkingDirectory();
+
+ const FileAction *file_action;
+ file_action = launch_info.GetFileActionForFD(STDIN_FILENO);
+ if (file_action) {
+ if (file_action->GetAction() == FileAction::eFileActionOpen)
+ stdin_file_spec = file_action->GetFileSpec();
+ }
+ file_action = launch_info.GetFileActionForFD(STDOUT_FILENO);
+ if (file_action) {
+ if (file_action->GetAction() == FileAction::eFileActionOpen)
+ stdout_file_spec = file_action->GetFileSpec();
+ }
+ file_action = launch_info.GetFileActionForFD(STDERR_FILENO);
+ if (file_action) {
+ if (file_action->GetAction() == FileAction::eFileActionOpen)
+ stderr_file_spec = file_action->GetFileSpec();
+ }
+
+ if (log) {
+ if (stdin_file_spec || stdout_file_spec || stderr_file_spec)
+ log->Printf("ProcessGDBRemote::%s provided with STDIO paths via "
+ "launch_info: stdin=%s, stdout=%s, stderr=%s",
+ __FUNCTION__,
+ stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
+ stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
+ stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
else
- {
- m_stdin_forward = true;
- }
-
- // ::LogSetBitMask (GDBR_LOG_DEFAULT);
- // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE | LLDB_LOG_OPTION_PREPEND_TIMESTAMP | LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
- // ::LogSetLogFile ("/dev/stdout");
-
- ObjectFile * object_file = exe_module->GetObjectFile();
- if (object_file)
- {
- error = EstablishConnectionIfNeeded (launch_info);
- if (error.Success())
- {
- lldb_utility::PseudoTerminal pty;
- const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
-
- PlatformSP platform_sp (GetTarget().GetPlatform());
- if (disable_stdio)
- {
- // set to /dev/null unless redirected to a file above
- if (!stdin_file_spec)
- stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);
- if (!stdout_file_spec)
- stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);
- if (!stderr_file_spec)
- stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);
- }
- else if (platform_sp && platform_sp->IsHost())
- {
- // If the debugserver is local and we aren't disabling STDIO, lets use
- // a pseudo terminal to instead of relying on the 'O' packets for stdio
- // since 'O' packets can really slow down debugging if the inferior
- // does a lot of output.
- if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
- pty.OpenFirstAvailableMaster(O_RDWR|O_NOCTTY, NULL, 0))
- {
- FileSpec slave_name{pty.GetSlaveName(NULL, 0), false};
-
- if (!stdin_file_spec)
- stdin_file_spec = slave_name;
-
- if (!stdout_file_spec)
- stdout_file_spec = slave_name;
-
- if (!stderr_file_spec)
- stderr_file_spec = slave_name;
- }
- if (log)
- log->Printf ("ProcessGDBRemote::%s adjusted STDIO paths for local platform (IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s",
- __FUNCTION__,
- stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
- stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
- stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
- }
-
- if (log)
- log->Printf ("ProcessGDBRemote::%s final STDIO paths after all adjustments: stdin=%s, stdout=%s, stderr=%s",
- __FUNCTION__,
- stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
- stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
- stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
-
- if (stdin_file_spec)
- m_gdb_comm.SetSTDIN(stdin_file_spec);
- if (stdout_file_spec)
- m_gdb_comm.SetSTDOUT(stdout_file_spec);
- if (stderr_file_spec)
- m_gdb_comm.SetSTDERR(stderr_file_spec);
-
- m_gdb_comm.SetDisableASLR (launch_flags & eLaunchFlagDisableASLR);
- m_gdb_comm.SetDetachOnError (launch_flags & eLaunchFlagDetachOnError);
-
- m_gdb_comm.SendLaunchArchPacket (GetTarget().GetArchitecture().GetArchitectureName());
-
- const char * launch_event_data = launch_info.GetLaunchEventData();
- if (launch_event_data != NULL && *launch_event_data != '\0')
- m_gdb_comm.SendLaunchEventDataPacket (launch_event_data);
-
- if (working_dir)
- {
- m_gdb_comm.SetWorkingDir (working_dir);
- }
-
- // Send the environment and the program + arguments after we connect
- const Args &environment = launch_info.GetEnvironmentEntries();
- if (environment.GetArgumentCount())
- {
- size_t num_environment_entries = environment.GetArgumentCount();
- for (size_t i=0; i<num_environment_entries; ++i)
- {
- const char *env_entry = environment.GetArgumentAtIndex(i);
- if (env_entry == NULL || m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
- break;
- }
- }
-
- {
- // Scope for the scoped timeout object
- GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10);
-
- int arg_packet_err = m_gdb_comm.SendArgumentsPacket (launch_info);
- if (arg_packet_err == 0)
- {
- std::string error_str;
- if (m_gdb_comm.GetLaunchSuccess (error_str))
- {
- SetID (m_gdb_comm.GetCurrentProcessID ());
- }
- else
- {
- error.SetErrorString (error_str.c_str());
- }
- }
- else
- {
- error.SetErrorStringWithFormat("'A' packet returned an error: %i", arg_packet_err);
- }
- }
-
- if (GetID() == LLDB_INVALID_PROCESS_ID)
- {
- if (log)
- log->Printf("failed to connect to debugserver: %s", error.AsCString());
- KillDebugserverProcess ();
- return error;
- }
-
- StringExtractorGDBRemote response;
- if (m_gdb_comm.GetStopReply(response))
- {
- SetLastStopPacket(response);
- // '?' Packets must be handled differently in non-stop mode
- if (GetTarget().GetNonStopModeEnabled())
- HandleStopReplySequence();
-
- const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture();
-
- if (process_arch.IsValid())
- {
- GetTarget().MergeArchitecture(process_arch);
- }
- else
- {
- const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();
- if (host_arch.IsValid())
- GetTarget().MergeArchitecture(host_arch);
- }
-
- SetPrivateState (SetThreadStopInfo (response));
-
- if (!disable_stdio)
- {
- if (pty.GetMasterFileDescriptor() != lldb_utility::PseudoTerminal::invalid_fd)
- SetSTDIOFileDescriptor (pty.ReleaseMasterFileDescriptor());
- }
- }
+ log->Printf("ProcessGDBRemote::%s no STDIO paths given via launch_info",
+ __FUNCTION__);
+ }
+
+ const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
+ if (stdin_file_spec || disable_stdio) {
+ // the inferior will be reading stdin from the specified file
+ // or stdio is completely disabled
+ m_stdin_forward = false;
+ } else {
+ m_stdin_forward = true;
+ }
+
+ // ::LogSetBitMask (GDBR_LOG_DEFAULT);
+ // ::LogSetOptions (LLDB_LOG_OPTION_THREADSAFE |
+ // LLDB_LOG_OPTION_PREPEND_TIMESTAMP |
+ // LLDB_LOG_OPTION_PREPEND_PROC_AND_THREAD);
+ // ::LogSetLogFile ("/dev/stdout");
+
+ ObjectFile *object_file = exe_module->GetObjectFile();
+ if (object_file) {
+ error = EstablishConnectionIfNeeded(launch_info);
+ if (error.Success()) {
+ lldb_utility::PseudoTerminal pty;
+ const bool disable_stdio = (launch_flags & eLaunchFlagDisableSTDIO) != 0;
+
+ PlatformSP platform_sp(GetTarget().GetPlatform());
+ if (disable_stdio) {
+ // set to /dev/null unless redirected to a file above
+ if (!stdin_file_spec)
+ stdin_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ if (!stdout_file_spec)
+ stdout_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ if (!stderr_file_spec)
+ stderr_file_spec.SetFile(FileSystem::DEV_NULL, false);
+ } else if (platform_sp && platform_sp->IsHost()) {
+ // If the debugserver is local and we aren't disabling STDIO, lets use
+ // a pseudo terminal to instead of relying on the 'O' packets for stdio
+ // since 'O' packets can really slow down debugging if the inferior
+ // does a lot of output.
+ if ((!stdin_file_spec || !stdout_file_spec || !stderr_file_spec) &&
+ pty.OpenFirstAvailableMaster(O_RDWR | O_NOCTTY, NULL, 0)) {
+ FileSpec slave_name{pty.GetSlaveName(NULL, 0), false};
+
+ if (!stdin_file_spec)
+ stdin_file_spec = slave_name;
+
+ if (!stdout_file_spec)
+ stdout_file_spec = slave_name;
+
+ if (!stderr_file_spec)
+ stderr_file_spec = slave_name;
}
- else
- {
- if (log)
- log->Printf("failed to connect to debugserver: %s", error.AsCString());
+ if (log)
+ log->Printf(
+ "ProcessGDBRemote::%s adjusted STDIO paths for local platform "
+ "(IsHost() is true) using slave: stdin=%s, stdout=%s, stderr=%s",
+ __FUNCTION__,
+ stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
+ stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
+ stderr_file_spec ? stderr_file_spec.GetCString() : "<null>");
+ }
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s final STDIO paths after all "
+ "adjustments: stdin=%s, stdout=%s, stderr=%s",
+ __FUNCTION__,
+ stdin_file_spec ? stdin_file_spec.GetCString() : "<null>",
+ stdout_file_spec ? stdout_file_spec.GetCString() : "<null>",
+ stderr_file_spec ? stderr_file_spec.GetCString()
+ : "<null>");
+
+ if (stdin_file_spec)
+ m_gdb_comm.SetSTDIN(stdin_file_spec);
+ if (stdout_file_spec)
+ m_gdb_comm.SetSTDOUT(stdout_file_spec);
+ if (stderr_file_spec)
+ m_gdb_comm.SetSTDERR(stderr_file_spec);
+
+ m_gdb_comm.SetDisableASLR(launch_flags & eLaunchFlagDisableASLR);
+ m_gdb_comm.SetDetachOnError(launch_flags & eLaunchFlagDetachOnError);
+
+ m_gdb_comm.SendLaunchArchPacket(
+ GetTarget().GetArchitecture().GetArchitectureName());
+
+ const char *launch_event_data = launch_info.GetLaunchEventData();
+ if (launch_event_data != NULL && *launch_event_data != '\0')
+ m_gdb_comm.SendLaunchEventDataPacket(launch_event_data);
+
+ if (working_dir) {
+ m_gdb_comm.SetWorkingDir(working_dir);
+ }
+
+ // Send the environment and the program + arguments after we connect
+ const Args &environment = launch_info.GetEnvironmentEntries();
+ if (environment.GetArgumentCount()) {
+ size_t num_environment_entries = environment.GetArgumentCount();
+ for (size_t i = 0; i < num_environment_entries; ++i) {
+ const char *env_entry = environment.GetArgumentAtIndex(i);
+ if (env_entry == NULL ||
+ m_gdb_comm.SendEnvironmentPacket(env_entry) != 0)
+ break;
}
- }
- else
- {
- // Set our user ID to an invalid process ID.
- SetID(LLDB_INVALID_PROCESS_ID);
- error.SetErrorStringWithFormat ("failed to get object file from '%s' for arch %s",
- exe_module->GetFileSpec().GetFilename().AsCString(),
- exe_module->GetArchitecture().GetArchitectureName());
- }
- return error;
-
-}
-
+ }
-Error
-ProcessGDBRemote::ConnectToDebugserver (const char *connect_url)
-{
- Error error;
- // Only connect if we have a valid connect URL
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ {
+ // Scope for the scoped timeout object
+ GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm,
+ std::chrono::seconds(10));
+
+ int arg_packet_err = m_gdb_comm.SendArgumentsPacket(launch_info);
+ if (arg_packet_err == 0) {
+ std::string error_str;
+ if (m_gdb_comm.GetLaunchSuccess(error_str)) {
+ SetID(m_gdb_comm.GetCurrentProcessID());
+ } else {
+ error.SetErrorString(error_str.c_str());
+ }
+ } else {
+ error.SetErrorStringWithFormat("'A' packet returned an error: %i",
+ arg_packet_err);
+ }
+ }
- if (connect_url && connect_url[0])
- {
+ if (GetID() == LLDB_INVALID_PROCESS_ID) {
if (log)
- log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__, connect_url);
- std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
- if (conn_ap.get())
- {
- const uint32_t max_retry_count = 50;
- uint32_t retry_count = 0;
- while (!m_gdb_comm.IsConnected())
- {
- if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess)
- {
- m_gdb_comm.SetConnection (conn_ap.release());
- break;
- }
- else if (error.WasInterrupted())
- {
- // If we were interrupted, don't keep retrying.
- break;
- }
+ log->Printf("failed to connect to debugserver: %s",
+ error.AsCString());
+ KillDebugserverProcess();
+ return error;
+ }
- retry_count++;
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.GetStopReply(response)) {
+ SetLastStopPacket(response);
+ // '?' Packets must be handled differently in non-stop mode
+ if (GetTarget().GetNonStopModeEnabled())
+ HandleStopReplySequence();
+
+ const ArchSpec &process_arch = m_gdb_comm.GetProcessArchitecture();
+
+ if (process_arch.IsValid()) {
+ GetTarget().MergeArchitecture(process_arch);
+ } else {
+ const ArchSpec &host_arch = m_gdb_comm.GetHostArchitecture();
+ if (host_arch.IsValid())
+ GetTarget().MergeArchitecture(host_arch);
+ }
- if (retry_count >= max_retry_count)
- break;
+ SetPrivateState(SetThreadStopInfo(response));
- usleep (100000);
- }
+ if (!disable_stdio) {
+ if (pty.GetMasterFileDescriptor() !=
+ lldb_utility::PseudoTerminal::invalid_fd)
+ SetSTDIOFileDescriptor(pty.ReleaseMasterFileDescriptor());
}
- }
+ }
+ } else {
+ if (log)
+ log->Printf("failed to connect to debugserver: %s", error.AsCString());
+ }
+ } else {
+ // Set our user ID to an invalid process ID.
+ SetID(LLDB_INVALID_PROCESS_ID);
+ error.SetErrorStringWithFormat(
+ "failed to get object file from '%s' for arch %s",
+ exe_module->GetFileSpec().GetFilename().AsCString(),
+ exe_module->GetArchitecture().GetArchitectureName());
+ }
+ return error;
+}
- if (!m_gdb_comm.IsConnected())
- {
- if (error.Success())
- error.SetErrorString("not connected to remote gdb server");
- return error;
- }
+Error ProcessGDBRemote::ConnectToDebugserver(llvm::StringRef connect_url) {
+ Error error;
+ // Only connect if we have a valid connect URL
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (!connect_url.empty()) {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s Connecting to %s", __FUNCTION__,
+ connect_url.str().c_str());
+ std::unique_ptr<ConnectionFileDescriptor> conn_ap(
+ new ConnectionFileDescriptor());
+ if (conn_ap.get()) {
+ const uint32_t max_retry_count = 50;
+ uint32_t retry_count = 0;
+ while (!m_gdb_comm.IsConnected()) {
+ if (conn_ap->Connect(connect_url, &error) == eConnectionStatusSuccess) {
+ m_gdb_comm.SetConnection(conn_ap.release());
+ break;
+ } else if (error.WasInterrupted()) {
+ // If we were interrupted, don't keep retrying.
+ break;
+ }
- // Start the communications read thread so all incoming data can be
- // parsed into packets and queued as they arrive.
- if (GetTarget().GetNonStopModeEnabled())
- m_gdb_comm.StartReadThread();
+ retry_count++;
- // We always seem to be able to open a connection to a local port
- // so we need to make sure we can then send data to it. If we can't
- // then we aren't actually connected to anything, so try and do the
- // handshake with the remote GDB server and make sure that goes
- // alright.
- if (!m_gdb_comm.HandshakeWithServer (&error))
- {
- m_gdb_comm.Disconnect();
- if (error.Success())
- error.SetErrorString("not connected to remote gdb server");
- return error;
+ if (retry_count >= max_retry_count)
+ break;
+
+ usleep(100000);
+ }
}
+ }
- // Send $QNonStop:1 packet on startup if required
- if (GetTarget().GetNonStopModeEnabled())
- GetTarget().SetNonStopModeEnabled (m_gdb_comm.SetNonStopMode(true));
+ if (!m_gdb_comm.IsConnected()) {
+ if (error.Success())
+ error.SetErrorString("not connected to remote gdb server");
+ return error;
+ }
+
+ // Start the communications read thread so all incoming data can be
+ // parsed into packets and queued as they arrive.
+ if (GetTarget().GetNonStopModeEnabled())
+ m_gdb_comm.StartReadThread();
+
+ // We always seem to be able to open a connection to a local port
+ // so we need to make sure we can then send data to it. If we can't
+ // then we aren't actually connected to anything, so try and do the
+ // handshake with the remote GDB server and make sure that goes
+ // alright.
+ if (!m_gdb_comm.HandshakeWithServer(&error)) {
+ m_gdb_comm.Disconnect();
+ if (error.Success())
+ error.SetErrorString("not connected to remote gdb server");
+ return error;
+ }
- m_gdb_comm.GetEchoSupported ();
- m_gdb_comm.GetThreadSuffixSupported ();
- m_gdb_comm.GetListThreadsInStopReplySupported ();
- m_gdb_comm.GetHostInfo ();
- m_gdb_comm.GetVContSupported ('c');
- m_gdb_comm.GetVAttachOrWaitSupported();
+ // Send $QNonStop:1 packet on startup if required
+ if (GetTarget().GetNonStopModeEnabled())
+ GetTarget().SetNonStopModeEnabled(m_gdb_comm.SetNonStopMode(true));
- // Ask the remote server for the default thread id
- if (GetTarget().GetNonStopModeEnabled())
- m_gdb_comm.GetDefaultThreadId(m_initial_tid);
+ m_gdb_comm.GetEchoSupported();
+ m_gdb_comm.GetThreadSuffixSupported();
+ m_gdb_comm.GetListThreadsInStopReplySupported();
+ m_gdb_comm.GetHostInfo();
+ m_gdb_comm.GetVContSupported('c');
+ m_gdb_comm.GetVAttachOrWaitSupported();
+ // Ask the remote server for the default thread id
+ if (GetTarget().GetNonStopModeEnabled())
+ m_gdb_comm.GetDefaultThreadId(m_initial_tid);
- size_t num_cmds = GetExtraStartupCommands().GetArgumentCount();
- for (size_t idx = 0; idx < num_cmds; idx++)
- {
- StringExtractorGDBRemote response;
- m_gdb_comm.SendPacketAndWaitForResponse (GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false);
- }
- return error;
+ size_t num_cmds = GetExtraStartupCommands().GetArgumentCount();
+ for (size_t idx = 0; idx < num_cmds; idx++) {
+ StringExtractorGDBRemote response;
+ m_gdb_comm.SendPacketAndWaitForResponse(
+ GetExtraStartupCommands().GetArgumentAtIndex(idx), response, false);
+ }
+ return error;
}
-void
-ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::DidLaunch()");
- if (GetID() != LLDB_INVALID_PROCESS_ID)
- {
- BuildDynamicRegisterInfo (false);
+void ProcessGDBRemote::DidLaunchOrAttach(ArchSpec &process_arch) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::%s()", __FUNCTION__);
+ if (GetID() != LLDB_INVALID_PROCESS_ID) {
+ BuildDynamicRegisterInfo(false);
- // See if the GDB server supports the qHostInfo information
+ // See if the GDB server supports the qHostInfo information
+ // See if the GDB server supports the qProcessInfo packet, if so
+ // prefer that over the Host information as it will be more specific
+ // to our process.
- // See if the GDB server supports the qProcessInfo packet, if so
- // prefer that over the Host information as it will be more specific
- // to our process.
+ const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
+ if (remote_process_arch.IsValid()) {
+ process_arch = remote_process_arch;
+ if (log)
+ log->Printf("ProcessGDBRemote::%s gdb-remote had process architecture, "
+ "using %s %s",
+ __FUNCTION__, process_arch.GetArchitectureName()
+ ? process_arch.GetArchitectureName()
+ : "<null>",
+ process_arch.GetTriple().getTriple().c_str()
+ ? process_arch.GetTriple().getTriple().c_str()
+ : "<null>");
+ } else {
+ process_arch = m_gdb_comm.GetHostArchitecture();
+ if (log)
+ log->Printf("ProcessGDBRemote::%s gdb-remote did not have process "
+ "architecture, using gdb-remote host architecture %s %s",
+ __FUNCTION__, process_arch.GetArchitectureName()
+ ? process_arch.GetArchitectureName()
+ : "<null>",
+ process_arch.GetTriple().getTriple().c_str()
+ ? process_arch.GetTriple().getTriple().c_str()
+ : "<null>");
+ }
+
+ if (process_arch.IsValid()) {
+ const ArchSpec &target_arch = GetTarget().GetArchitecture();
+ if (target_arch.IsValid()) {
+ if (log)
+ log->Printf(
+ "ProcessGDBRemote::%s analyzing target arch, currently %s %s",
+ __FUNCTION__, target_arch.GetArchitectureName()
+ ? target_arch.GetArchitectureName()
+ : "<null>",
+ target_arch.GetTriple().getTriple().c_str()
+ ? target_arch.GetTriple().getTriple().c_str()
+ : "<null>");
+
+ // If the remote host is ARM and we have apple as the vendor, then
+ // ARM executables and shared libraries can have mixed ARM
+ // architectures.
+ // You can have an armv6 executable, and if the host is armv7, then the
+ // system will load the best possible architecture for all shared
+ // libraries
+ // it has, so we really need to take the remote host architecture as our
+ // defacto architecture in this case.
+
+ if ((process_arch.GetMachine() == llvm::Triple::arm ||
+ process_arch.GetMachine() == llvm::Triple::thumb) &&
+ process_arch.GetTriple().getVendor() == llvm::Triple::Apple) {
+ GetTarget().SetArchitecture(process_arch);
+ if (log)
+ log->Printf("ProcessGDBRemote::%s remote process is ARM/Apple, "
+ "setting target arch to %s %s",
+ __FUNCTION__, process_arch.GetArchitectureName()
+ ? process_arch.GetArchitectureName()
+ : "<null>",
+ process_arch.GetTriple().getTriple().c_str()
+ ? process_arch.GetTriple().getTriple().c_str()
+ : "<null>");
+ } else {
+ // Fill in what is missing in the triple
+ const llvm::Triple &remote_triple = process_arch.GetTriple();
+ llvm::Triple new_target_triple = target_arch.GetTriple();
+ if (new_target_triple.getVendorName().size() == 0) {
+ new_target_triple.setVendor(remote_triple.getVendor());
+
+ if (new_target_triple.getOSName().size() == 0) {
+ new_target_triple.setOS(remote_triple.getOS());
+
+ if (new_target_triple.getEnvironmentName().size() == 0)
+ new_target_triple.setEnvironment(
+ remote_triple.getEnvironment());
+ }
- const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture();
- if (remote_process_arch.IsValid())
- {
- process_arch = remote_process_arch;
- if (log)
- log->Printf ("ProcessGDBRemote::%s gdb-remote had process architecture, using %s %s",
- __FUNCTION__,
- process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
- process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
+ ArchSpec new_target_arch = target_arch;
+ new_target_arch.SetTriple(new_target_triple);
+ GetTarget().SetArchitecture(new_target_arch);
+ }
}
- else
- {
- process_arch = m_gdb_comm.GetHostArchitecture();
- if (log)
- log->Printf ("ProcessGDBRemote::%s gdb-remote did not have process architecture, using gdb-remote host architecture %s %s",
- __FUNCTION__,
- process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
- process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
- }
-
- if (process_arch.IsValid())
- {
- const ArchSpec &target_arch = GetTarget().GetArchitecture();
- if (target_arch.IsValid())
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s analyzing target arch, currently %s %s",
- __FUNCTION__,
- target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>",
- target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>");
-
- // If the remote host is ARM and we have apple as the vendor, then
- // ARM executables and shared libraries can have mixed ARM architectures.
- // You can have an armv6 executable, and if the host is armv7, then the
- // system will load the best possible architecture for all shared libraries
- // it has, so we really need to take the remote host architecture as our
- // defacto architecture in this case.
-
- if ((process_arch.GetMachine() == llvm::Triple::arm || process_arch.GetMachine() == llvm::Triple::thumb)
- && process_arch.GetTriple().getVendor() == llvm::Triple::Apple)
- {
- GetTarget().SetArchitecture (process_arch);
- if (log)
- log->Printf ("ProcessGDBRemote::%s remote process is ARM/Apple, setting target arch to %s %s",
- __FUNCTION__,
- process_arch.GetArchitectureName () ? process_arch.GetArchitectureName () : "<null>",
- process_arch.GetTriple().getTriple ().c_str() ? process_arch.GetTriple().getTriple ().c_str() : "<null>");
- }
- else
- {
- // Fill in what is missing in the triple
- const llvm::Triple &remote_triple = process_arch.GetTriple();
- llvm::Triple new_target_triple = target_arch.GetTriple();
- if (new_target_triple.getVendorName().size() == 0)
- {
- new_target_triple.setVendor (remote_triple.getVendor());
-
- if (new_target_triple.getOSName().size() == 0)
- {
- new_target_triple.setOS (remote_triple.getOS());
-
- if (new_target_triple.getEnvironmentName().size() == 0)
- new_target_triple.setEnvironment (remote_triple.getEnvironment());
- }
-
- ArchSpec new_target_arch = target_arch;
- new_target_arch.SetTriple(new_target_triple);
- GetTarget().SetArchitecture(new_target_arch);
- }
- }
- if (log)
- log->Printf ("ProcessGDBRemote::%s final target arch after adjustments for remote architecture: %s %s",
- __FUNCTION__,
- target_arch.GetArchitectureName () ? target_arch.GetArchitectureName () : "<null>",
- target_arch.GetTriple().getTriple ().c_str() ? target_arch.GetTriple().getTriple ().c_str() : "<null>");
- }
- else
- {
- // The target doesn't have a valid architecture yet, set it from
- // the architecture we got from the remote GDB server
- GetTarget().SetArchitecture (process_arch);
- }
- }
- }
+ if (log)
+ log->Printf("ProcessGDBRemote::%s final target arch after "
+ "adjustments for remote architecture: %s %s",
+ __FUNCTION__, target_arch.GetArchitectureName()
+ ? target_arch.GetArchitectureName()
+ : "<null>",
+ target_arch.GetTriple().getTriple().c_str()
+ ? target_arch.GetTriple().getTriple().c_str()
+ : "<null>");
+ } else {
+ // The target doesn't have a valid architecture yet, set it from
+ // the architecture we got from the remote GDB server
+ GetTarget().SetArchitecture(process_arch);
+ }
+ }
+
+ // Find out which StructuredDataPlugins are supported by the
+ // debug monitor. These plugins transmit data over async $J packets.
+ auto supported_packets_array =
+ m_gdb_comm.GetSupportedStructuredDataPlugins();
+ if (supported_packets_array)
+ MapSupportedStructuredDataPlugins(*supported_packets_array);
+ }
}
-void
-ProcessGDBRemote::DidLaunch ()
-{
- ArchSpec process_arch;
- DidLaunchOrAttach (process_arch);
+void ProcessGDBRemote::DidLaunch() {
+ ArchSpec process_arch;
+ DidLaunchOrAttach(process_arch);
}
-Error
-ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- Error error;
-
- if (log)
- log->Printf ("ProcessGDBRemote::%s()", __FUNCTION__);
-
- // Clear out and clean up from any current state
- Clear();
- if (attach_pid != LLDB_INVALID_PROCESS_ID)
- {
- error = EstablishConnectionIfNeeded (attach_info);
- if (error.Success())
- {
- m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
-
- char packet[64];
- const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid);
- SetID (attach_pid);
- m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet, packet_len));
- }
- else
- SetExitStatus (-1, error.AsCString());
- }
-
- return error;
+Error ProcessGDBRemote::DoAttachToProcessWithID(
+ lldb::pid_t attach_pid, const ProcessAttachInfo &attach_info) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ Error error;
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s()", __FUNCTION__);
+
+ // Clear out and clean up from any current state
+ Clear();
+ if (attach_pid != LLDB_INVALID_PROCESS_ID) {
+ error = EstablishConnectionIfNeeded(attach_info);
+ if (error.Success()) {
+ m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
+
+ char packet[64];
+ const int packet_len =
+ ::snprintf(packet, sizeof(packet), "vAttach;%" PRIx64, attach_pid);
+ SetID(attach_pid);
+ m_async_broadcaster.BroadcastEvent(
+ eBroadcastBitAsyncContinue, new EventDataBytes(packet, packet_len));
+ } else
+ SetExitStatus(-1, error.AsCString());
+ }
+
+ return error;
}
-Error
-ProcessGDBRemote::DoAttachToProcessWithName (const char *process_name, const ProcessAttachInfo &attach_info)
-{
- Error error;
- // Clear out and clean up from any current state
- Clear();
-
- if (process_name && process_name[0])
- {
- error = EstablishConnectionIfNeeded (attach_info);
- if (error.Success())
- {
- StreamString packet;
-
- m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
-
- if (attach_info.GetWaitForLaunch())
- {
- if (!m_gdb_comm.GetVAttachOrWaitSupported())
- {
- packet.PutCString ("vAttachWait");
- }
- else
- {
- if (attach_info.GetIgnoreExisting())
- packet.PutCString("vAttachWait");
- else
- packet.PutCString ("vAttachOrWait");
- }
- }
- else
- packet.PutCString("vAttachName");
- packet.PutChar(';');
- packet.PutBytesAsRawHex8(process_name, strlen(process_name), endian::InlHostByteOrder(), endian::InlHostByteOrder());
-
- m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (packet.GetData(), packet.GetSize()));
-
+Error ProcessGDBRemote::DoAttachToProcessWithName(
+ const char *process_name, const ProcessAttachInfo &attach_info) {
+ Error error;
+ // Clear out and clean up from any current state
+ Clear();
+
+ if (process_name && process_name[0]) {
+ error = EstablishConnectionIfNeeded(attach_info);
+ if (error.Success()) {
+ StreamString packet;
+
+ m_gdb_comm.SetDetachOnError(attach_info.GetDetachOnError());
+
+ if (attach_info.GetWaitForLaunch()) {
+ if (!m_gdb_comm.GetVAttachOrWaitSupported()) {
+ packet.PutCString("vAttachWait");
+ } else {
+ if (attach_info.GetIgnoreExisting())
+ packet.PutCString("vAttachWait");
+ else
+ packet.PutCString("vAttachOrWait");
}
- else
- SetExitStatus (-1, error.AsCString());
- }
- return error;
+ } else
+ packet.PutCString("vAttachName");
+ packet.PutChar(';');
+ packet.PutBytesAsRawHex8(process_name, strlen(process_name),
+ endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
+
+ m_async_broadcaster.BroadcastEvent(
+ eBroadcastBitAsyncContinue,
+ new EventDataBytes(packet.GetString().data(), packet.GetSize()));
+
+ } else
+ SetExitStatus(-1, error.AsCString());
+ }
+ return error;
}
-void
-ProcessGDBRemote::DidExit ()
-{
- // When we exit, disconnect from the GDB server communications
- m_gdb_comm.Disconnect();
+void ProcessGDBRemote::DidExit() {
+ // When we exit, disconnect from the GDB server communications
+ m_gdb_comm.Disconnect();
}
-void
-ProcessGDBRemote::DidAttach (ArchSpec &process_arch)
-{
- // If you can figure out what the architecture is, fill it in here.
- process_arch.Clear();
- DidLaunchOrAttach (process_arch);
+void ProcessGDBRemote::DidAttach(ArchSpec &process_arch) {
+ // If you can figure out what the architecture is, fill it in here.
+ process_arch.Clear();
+ DidLaunchOrAttach(process_arch);
}
-
-Error
-ProcessGDBRemote::WillResume ()
-{
- m_continue_c_tids.clear();
- m_continue_C_tids.clear();
- m_continue_s_tids.clear();
- m_continue_S_tids.clear();
- m_jstopinfo_sp.reset();
- m_jthreadsinfo_sp.reset();
- return Error();
+Error ProcessGDBRemote::WillResume() {
+ m_continue_c_tids.clear();
+ m_continue_C_tids.clear();
+ m_continue_s_tids.clear();
+ m_continue_S_tids.clear();
+ m_jstopinfo_sp.reset();
+ m_jthreadsinfo_sp.reset();
+ return Error();
}
-Error
-ProcessGDBRemote::DoResume ()
-{
- Error error;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::Resume()");
-
- ListenerSP listener_sp (Listener::MakeListener("gdb-remote.resume-packet-sent"));
- if (listener_sp->StartListeningForEvents (&m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent))
- {
- listener_sp->StartListeningForEvents (&m_async_broadcaster, ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit);
-
- const size_t num_threads = GetThreadList().GetSize();
-
- StreamString continue_packet;
- bool continue_packet_error = false;
- if (m_gdb_comm.HasAnyVContSupport ())
- {
- if (!GetTarget().GetNonStopModeEnabled() &&
- (m_continue_c_tids.size() == num_threads ||
- (m_continue_c_tids.empty() &&
- m_continue_C_tids.empty() &&
- m_continue_s_tids.empty() &&
- m_continue_S_tids.empty())))
- {
- // All threads are continuing, just send a "c" packet
- continue_packet.PutCString ("c");
- }
- else
- {
- continue_packet.PutCString ("vCont");
-
- if (!m_continue_c_tids.empty())
- {
- if (m_gdb_comm.GetVContSupported ('c'))
- {
- for (tid_collection::const_iterator t_pos = m_continue_c_tids.begin(), t_end = m_continue_c_tids.end(); t_pos != t_end; ++t_pos)
- continue_packet.Printf(";c:%4.4" PRIx64, *t_pos);
- }
- else
- continue_packet_error = true;
- }
-
- if (!continue_packet_error && !m_continue_C_tids.empty())
- {
- if (m_gdb_comm.GetVContSupported ('C'))
- {
- for (tid_sig_collection::const_iterator s_pos = m_continue_C_tids.begin(), s_end = m_continue_C_tids.end(); s_pos != s_end; ++s_pos)
- continue_packet.Printf(";C%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first);
- }
- else
- continue_packet_error = true;
- }
-
- if (!continue_packet_error && !m_continue_s_tids.empty())
- {
- if (m_gdb_comm.GetVContSupported ('s'))
- {
- for (tid_collection::const_iterator t_pos = m_continue_s_tids.begin(), t_end = m_continue_s_tids.end(); t_pos != t_end; ++t_pos)
- continue_packet.Printf(";s:%4.4" PRIx64, *t_pos);
- }
- else
- continue_packet_error = true;
- }
+Error ProcessGDBRemote::DoResume() {
+ Error error;
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::Resume()");
+
+ ListenerSP listener_sp(
+ Listener::MakeListener("gdb-remote.resume-packet-sent"));
+ if (listener_sp->StartListeningForEvents(
+ &m_gdb_comm, GDBRemoteCommunication::eBroadcastBitRunPacketSent)) {
+ listener_sp->StartListeningForEvents(
+ &m_async_broadcaster,
+ ProcessGDBRemote::eBroadcastBitAsyncThreadDidExit);
+
+ const size_t num_threads = GetThreadList().GetSize();
+
+ StreamString continue_packet;
+ bool continue_packet_error = false;
+ if (m_gdb_comm.HasAnyVContSupport()) {
+ if (!GetTarget().GetNonStopModeEnabled() &&
+ (m_continue_c_tids.size() == num_threads ||
+ (m_continue_c_tids.empty() && m_continue_C_tids.empty() &&
+ m_continue_s_tids.empty() && m_continue_S_tids.empty()))) {
+ // All threads are continuing, just send a "c" packet
+ continue_packet.PutCString("c");
+ } else {
+ continue_packet.PutCString("vCont");
+
+ if (!m_continue_c_tids.empty()) {
+ if (m_gdb_comm.GetVContSupported('c')) {
+ for (tid_collection::const_iterator
+ t_pos = m_continue_c_tids.begin(),
+ t_end = m_continue_c_tids.end();
+ t_pos != t_end; ++t_pos)
+ continue_packet.Printf(";c:%4.4" PRIx64, *t_pos);
+ } else
+ continue_packet_error = true;
+ }
- if (!continue_packet_error && !m_continue_S_tids.empty())
- {
- if (m_gdb_comm.GetVContSupported ('S'))
- {
- for (tid_sig_collection::const_iterator s_pos = m_continue_S_tids.begin(), s_end = m_continue_S_tids.end(); s_pos != s_end; ++s_pos)
- continue_packet.Printf(";S%2.2x:%4.4" PRIx64, s_pos->second, s_pos->first);
- }
- else
- continue_packet_error = true;
- }
+ if (!continue_packet_error && !m_continue_C_tids.empty()) {
+ if (m_gdb_comm.GetVContSupported('C')) {
+ for (tid_sig_collection::const_iterator
+ s_pos = m_continue_C_tids.begin(),
+ s_end = m_continue_C_tids.end();
+ s_pos != s_end; ++s_pos)
+ continue_packet.Printf(";C%2.2x:%4.4" PRIx64, s_pos->second,
+ s_pos->first);
+ } else
+ continue_packet_error = true;
+ }
- if (continue_packet_error)
- continue_packet.GetString().clear();
- }
+ if (!continue_packet_error && !m_continue_s_tids.empty()) {
+ if (m_gdb_comm.GetVContSupported('s')) {
+ for (tid_collection::const_iterator
+ t_pos = m_continue_s_tids.begin(),
+ t_end = m_continue_s_tids.end();
+ t_pos != t_end; ++t_pos)
+ continue_packet.Printf(";s:%4.4" PRIx64, *t_pos);
+ } else
+ continue_packet_error = true;
}
- else
+
+ if (!continue_packet_error && !m_continue_S_tids.empty()) {
+ if (m_gdb_comm.GetVContSupported('S')) {
+ for (tid_sig_collection::const_iterator
+ s_pos = m_continue_S_tids.begin(),
+ s_end = m_continue_S_tids.end();
+ s_pos != s_end; ++s_pos)
+ continue_packet.Printf(";S%2.2x:%4.4" PRIx64, s_pos->second,
+ s_pos->first);
+ } else
continue_packet_error = true;
+ }
if (continue_packet_error)
- {
- // Either no vCont support, or we tried to use part of the vCont
- // packet that wasn't supported by the remote GDB server.
- // We need to try and make a simple packet that can do our continue
- const size_t num_continue_c_tids = m_continue_c_tids.size();
- const size_t num_continue_C_tids = m_continue_C_tids.size();
- const size_t num_continue_s_tids = m_continue_s_tids.size();
- const size_t num_continue_S_tids = m_continue_S_tids.size();
- if (num_continue_c_tids > 0)
- {
- if (num_continue_c_tids == num_threads)
- {
- // All threads are resuming...
- m_gdb_comm.SetCurrentThreadForRun (-1);
- continue_packet.PutChar ('c');
- continue_packet_error = false;
- }
- else if (num_continue_c_tids == 1 &&
- num_continue_C_tids == 0 &&
- num_continue_s_tids == 0 &&
- num_continue_S_tids == 0 )
- {
- // Only one thread is continuing
- m_gdb_comm.SetCurrentThreadForRun (m_continue_c_tids.front());
- continue_packet.PutChar ('c');
- continue_packet_error = false;
- }
+ continue_packet.Clear();
+ }
+ } else
+ continue_packet_error = true;
+
+ if (continue_packet_error) {
+ // Either no vCont support, or we tried to use part of the vCont
+ // packet that wasn't supported by the remote GDB server.
+ // We need to try and make a simple packet that can do our continue
+ const size_t num_continue_c_tids = m_continue_c_tids.size();
+ const size_t num_continue_C_tids = m_continue_C_tids.size();
+ const size_t num_continue_s_tids = m_continue_s_tids.size();
+ const size_t num_continue_S_tids = m_continue_S_tids.size();
+ if (num_continue_c_tids > 0) {
+ if (num_continue_c_tids == num_threads) {
+ // All threads are resuming...
+ m_gdb_comm.SetCurrentThreadForRun(-1);
+ continue_packet.PutChar('c');
+ continue_packet_error = false;
+ } else if (num_continue_c_tids == 1 && num_continue_C_tids == 0 &&
+ num_continue_s_tids == 0 && num_continue_S_tids == 0) {
+ // Only one thread is continuing
+ m_gdb_comm.SetCurrentThreadForRun(m_continue_c_tids.front());
+ continue_packet.PutChar('c');
+ continue_packet_error = false;
+ }
+ }
+
+ if (continue_packet_error && num_continue_C_tids > 0) {
+ if ((num_continue_C_tids + num_continue_c_tids) == num_threads &&
+ num_continue_C_tids > 0 && num_continue_s_tids == 0 &&
+ num_continue_S_tids == 0) {
+ const int continue_signo = m_continue_C_tids.front().second;
+ // Only one thread is continuing
+ if (num_continue_C_tids > 1) {
+ // More that one thread with a signal, yet we don't have
+ // vCont support and we are being asked to resume each
+ // thread with a signal, we need to make sure they are
+ // all the same signal, or we can't issue the continue
+ // accurately with the current support...
+ if (num_continue_C_tids > 1) {
+ continue_packet_error = false;
+ for (size_t i = 1; i < m_continue_C_tids.size(); ++i) {
+ if (m_continue_C_tids[i].second != continue_signo)
+ continue_packet_error = true;
+ }
}
+ if (!continue_packet_error)
+ m_gdb_comm.SetCurrentThreadForRun(-1);
+ } else {
+ // Set the continue thread ID
+ continue_packet_error = false;
+ m_gdb_comm.SetCurrentThreadForRun(m_continue_C_tids.front().first);
+ }
+ if (!continue_packet_error) {
+ // Add threads continuing with the same signo...
+ continue_packet.Printf("C%2.2x", continue_signo);
+ }
+ }
+ }
- if (continue_packet_error && num_continue_C_tids > 0)
- {
- if ((num_continue_C_tids + num_continue_c_tids) == num_threads &&
- num_continue_C_tids > 0 &&
- num_continue_s_tids == 0 &&
- num_continue_S_tids == 0 )
- {
- const int continue_signo = m_continue_C_tids.front().second;
- // Only one thread is continuing
- if (num_continue_C_tids > 1)
- {
- // More that one thread with a signal, yet we don't have
- // vCont support and we are being asked to resume each
- // thread with a signal, we need to make sure they are
- // all the same signal, or we can't issue the continue
- // accurately with the current support...
- if (num_continue_C_tids > 1)
- {
- continue_packet_error = false;
- for (size_t i=1; i<m_continue_C_tids.size(); ++i)
- {
- if (m_continue_C_tids[i].second != continue_signo)
- continue_packet_error = true;
- }
- }
- if (!continue_packet_error)
- m_gdb_comm.SetCurrentThreadForRun (-1);
- }
- else
- {
- // Set the continue thread ID
- continue_packet_error = false;
- m_gdb_comm.SetCurrentThreadForRun (m_continue_C_tids.front().first);
- }
- if (!continue_packet_error)
- {
- // Add threads continuing with the same signo...
- continue_packet.Printf("C%2.2x", continue_signo);
- }
- }
- }
+ if (continue_packet_error && num_continue_s_tids > 0) {
+ if (num_continue_s_tids == num_threads) {
+ // All threads are resuming...
+ m_gdb_comm.SetCurrentThreadForRun(-1);
- if (continue_packet_error && num_continue_s_tids > 0)
- {
- if (num_continue_s_tids == num_threads)
- {
- // All threads are resuming...
- m_gdb_comm.SetCurrentThreadForRun (-1);
-
- // If in Non-Stop-Mode use vCont when stepping
- if (GetTarget().GetNonStopModeEnabled())
- {
- if (m_gdb_comm.GetVContSupported('s'))
- continue_packet.PutCString("vCont;s");
- else
- continue_packet.PutChar('s');
- }
- else
- continue_packet.PutChar('s');
-
- continue_packet_error = false;
- }
- else if (num_continue_c_tids == 0 &&
- num_continue_C_tids == 0 &&
- num_continue_s_tids == 1 &&
- num_continue_S_tids == 0 )
- {
- // Only one thread is stepping
- m_gdb_comm.SetCurrentThreadForRun (m_continue_s_tids.front());
- continue_packet.PutChar ('s');
- continue_packet_error = false;
- }
- }
-
- if (!continue_packet_error && num_continue_S_tids > 0)
- {
- if (num_continue_S_tids == num_threads)
- {
- const int step_signo = m_continue_S_tids.front().second;
- // Are all threads trying to step with the same signal?
- continue_packet_error = false;
- if (num_continue_S_tids > 1)
- {
- for (size_t i=1; i<num_threads; ++i)
- {
- if (m_continue_S_tids[i].second != step_signo)
- continue_packet_error = true;
- }
- }
- if (!continue_packet_error)
- {
- // Add threads stepping with the same signo...
- m_gdb_comm.SetCurrentThreadForRun (-1);
- continue_packet.Printf("S%2.2x", step_signo);
- }
- }
- else if (num_continue_c_tids == 0 &&
- num_continue_C_tids == 0 &&
- num_continue_s_tids == 0 &&
- num_continue_S_tids == 1 )
- {
- // Only one thread is stepping with signal
- m_gdb_comm.SetCurrentThreadForRun (m_continue_S_tids.front().first);
- continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
- continue_packet_error = false;
- }
+ // If in Non-Stop-Mode use vCont when stepping
+ if (GetTarget().GetNonStopModeEnabled()) {
+ if (m_gdb_comm.GetVContSupported('s'))
+ continue_packet.PutCString("vCont;s");
+ else
+ continue_packet.PutChar('s');
+ } else
+ continue_packet.PutChar('s');
+
+ continue_packet_error = false;
+ } else if (num_continue_c_tids == 0 && num_continue_C_tids == 0 &&
+ num_continue_s_tids == 1 && num_continue_S_tids == 0) {
+ // Only one thread is stepping
+ m_gdb_comm.SetCurrentThreadForRun(m_continue_s_tids.front());
+ continue_packet.PutChar('s');
+ continue_packet_error = false;
+ }
+ }
+
+ if (!continue_packet_error && num_continue_S_tids > 0) {
+ if (num_continue_S_tids == num_threads) {
+ const int step_signo = m_continue_S_tids.front().second;
+ // Are all threads trying to step with the same signal?
+ continue_packet_error = false;
+ if (num_continue_S_tids > 1) {
+ for (size_t i = 1; i < num_threads; ++i) {
+ if (m_continue_S_tids[i].second != step_signo)
+ continue_packet_error = true;
}
+ }
+ if (!continue_packet_error) {
+ // Add threads stepping with the same signo...
+ m_gdb_comm.SetCurrentThreadForRun(-1);
+ continue_packet.Printf("S%2.2x", step_signo);
+ }
+ } else if (num_continue_c_tids == 0 && num_continue_C_tids == 0 &&
+ num_continue_s_tids == 0 && num_continue_S_tids == 1) {
+ // Only one thread is stepping with signal
+ m_gdb_comm.SetCurrentThreadForRun(m_continue_S_tids.front().first);
+ continue_packet.Printf("S%2.2x", m_continue_S_tids.front().second);
+ continue_packet_error = false;
}
+ }
+ }
- if (continue_packet_error)
- {
- error.SetErrorString ("can't make continue packet for this resume");
- }
- else
- {
- EventSP event_sp;
- TimeValue timeout;
- timeout = TimeValue::Now();
- timeout.OffsetWithSeconds (5);
- if (!m_async_thread.IsJoinable())
- {
- error.SetErrorString ("Trying to resume but the async thread is dead.");
- if (log)
- log->Printf ("ProcessGDBRemote::DoResume: Trying to resume but the async thread is dead.");
- return error;
- }
+ if (continue_packet_error) {
+ error.SetErrorString("can't make continue packet for this resume");
+ } else {
+ EventSP event_sp;
+ if (!m_async_thread.IsJoinable()) {
+ error.SetErrorString("Trying to resume but the async thread is dead.");
+ if (log)
+ log->Printf("ProcessGDBRemote::DoResume: Trying to resume but the "
+ "async thread is dead.");
+ return error;
+ }
- m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncContinue, new EventDataBytes (continue_packet.GetData(), continue_packet.GetSize()));
+ m_async_broadcaster.BroadcastEvent(
+ eBroadcastBitAsyncContinue,
+ new EventDataBytes(continue_packet.GetString().data(),
+ continue_packet.GetSize()));
- if (listener_sp->WaitForEvent (&timeout, event_sp) == false)
- {
- error.SetErrorString("Resume timed out.");
- if (log)
- log->Printf ("ProcessGDBRemote::DoResume: Resume timed out.");
- }
- else if (event_sp->BroadcasterIs (&m_async_broadcaster))
- {
- error.SetErrorString ("Broadcast continue, but the async thread was killed before we got an ack back.");
- if (log)
- log->Printf ("ProcessGDBRemote::DoResume: Broadcast continue, but the async thread was killed before we got an ack back.");
- return error;
- }
- }
+ if (listener_sp->GetEvent(event_sp, std::chrono::seconds(5)) == false) {
+ error.SetErrorString("Resume timed out.");
+ if (log)
+ log->Printf("ProcessGDBRemote::DoResume: Resume timed out.");
+ } else if (event_sp->BroadcasterIs(&m_async_broadcaster)) {
+ error.SetErrorString("Broadcast continue, but the async thread was "
+ "killed before we got an ack back.");
+ if (log)
+ log->Printf("ProcessGDBRemote::DoResume: Broadcast continue, but the "
+ "async thread was killed before we got an ack back.");
+ return error;
+ }
}
+ }
- return error;
+ return error;
}
-void
-ProcessGDBRemote::HandleStopReplySequence ()
-{
- while(true)
- {
- // Send vStopped
- StringExtractorGDBRemote response;
- m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false);
+void ProcessGDBRemote::HandleStopReplySequence() {
+ while (true) {
+ // Send vStopped
+ StringExtractorGDBRemote response;
+ m_gdb_comm.SendPacketAndWaitForResponse("vStopped", response, false);
- // OK represents end of signal list
- if (response.IsOKResponse())
- break;
+ // OK represents end of signal list
+ if (response.IsOKResponse())
+ break;
- // If not OK or a normal packet we have a problem
- if (!response.IsNormalResponse())
- break;
+ // If not OK or a normal packet we have a problem
+ if (!response.IsNormalResponse())
+ break;
- SetLastStopPacket(response);
- }
+ SetLastStopPacket(response);
+ }
}
-void
-ProcessGDBRemote::ClearThreadIDList ()
-{
- std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
- m_thread_ids.clear();
- m_thread_pcs.clear();
+void ProcessGDBRemote::ClearThreadIDList() {
+ std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
+ m_thread_ids.clear();
+ m_thread_pcs.clear();
}
size_t
-ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue (std::string &value)
-{
- m_thread_ids.clear();
- m_thread_pcs.clear();
- size_t comma_pos;
- lldb::tid_t tid;
- while ((comma_pos = value.find(',')) != std::string::npos)
- {
- value[comma_pos] = '\0';
- // thread in big endian hex
- tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
- if (tid != LLDB_INVALID_THREAD_ID)
- m_thread_ids.push_back (tid);
- value.erase(0, comma_pos + 1);
- }
- tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
+ProcessGDBRemote::UpdateThreadIDsFromStopReplyThreadsValue(std::string &value) {
+ m_thread_ids.clear();
+ m_thread_pcs.clear();
+ size_t comma_pos;
+ lldb::tid_t tid;
+ while ((comma_pos = value.find(',')) != std::string::npos) {
+ value[comma_pos] = '\0';
+ // thread in big endian hex
+ tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16);
if (tid != LLDB_INVALID_THREAD_ID)
- m_thread_ids.push_back (tid);
- return m_thread_ids.size();
+ m_thread_ids.push_back(tid);
+ value.erase(0, comma_pos + 1);
+ }
+ tid = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_THREAD_ID, 16);
+ if (tid != LLDB_INVALID_THREAD_ID)
+ m_thread_ids.push_back(tid);
+ return m_thread_ids.size();
}
size_t
-ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue (std::string &value)
-{
- m_thread_pcs.clear();
- size_t comma_pos;
- lldb::addr_t pc;
- while ((comma_pos = value.find(',')) != std::string::npos)
- {
- value[comma_pos] = '\0';
- pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
- if (pc != LLDB_INVALID_ADDRESS)
- m_thread_pcs.push_back (pc);
- value.erase(0, comma_pos + 1);
- }
- pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
- if (pc != LLDB_INVALID_THREAD_ID)
- m_thread_pcs.push_back (pc);
- return m_thread_pcs.size();
+ProcessGDBRemote::UpdateThreadPCsFromStopReplyThreadsValue(std::string &value) {
+ m_thread_pcs.clear();
+ size_t comma_pos;
+ lldb::addr_t pc;
+ while ((comma_pos = value.find(',')) != std::string::npos) {
+ value[comma_pos] = '\0';
+ pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_ADDRESS)
+ m_thread_pcs.push_back(pc);
+ value.erase(0, comma_pos + 1);
+ }
+ pc = StringConvert::ToUInt64(value.c_str(), LLDB_INVALID_ADDRESS, 16);
+ if (pc != LLDB_INVALID_THREAD_ID)
+ m_thread_pcs.push_back(pc);
+ return m_thread_pcs.size();
}
-bool
-ProcessGDBRemote::UpdateThreadIDList ()
-{
- std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
-
- if (m_jthreadsinfo_sp)
- {
- // If we have the JSON threads info, we can get the thread list from that
- StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
- if (thread_infos && thread_infos->GetSize() > 0)
- {
- m_thread_ids.clear();
- m_thread_pcs.clear();
- thread_infos->ForEach([this](StructuredData::Object* object) -> bool {
- StructuredData::Dictionary *thread_dict = object->GetAsDictionary();
- if (thread_dict)
- {
- // Set the thread stop info from the JSON dictionary
- SetThreadStopInfo (thread_dict);
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid))
- m_thread_ids.push_back(tid);
- }
- return true; // Keep iterating through all thread_info objects
- });
+bool ProcessGDBRemote::UpdateThreadIDList() {
+ std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
+
+ if (m_jthreadsinfo_sp) {
+ // If we have the JSON threads info, we can get the thread list from that
+ StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
+ if (thread_infos && thread_infos->GetSize() > 0) {
+ m_thread_ids.clear();
+ m_thread_pcs.clear();
+ thread_infos->ForEach([this](StructuredData::Object *object) -> bool {
+ StructuredData::Dictionary *thread_dict = object->GetAsDictionary();
+ if (thread_dict) {
+ // Set the thread stop info from the JSON dictionary
+ SetThreadStopInfo(thread_dict);
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+ if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid))
+ m_thread_ids.push_back(tid);
+ }
+ return true; // Keep iterating through all thread_info objects
+ });
+ }
+ if (!m_thread_ids.empty())
+ return true;
+ } else {
+ // See if we can get the thread IDs from the current stop reply packets
+ // that might contain a "threads" key/value pair
+
+ // Lock the thread stack while we access it
+ // Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
+ std::unique_lock<std::recursive_mutex> stop_stack_lock(
+ m_last_stop_packet_mutex, std::defer_lock);
+ if (stop_stack_lock.try_lock()) {
+ // Get the number of stop packets on the stack
+ int nItems = m_stop_packet_stack.size();
+ // Iterate over them
+ for (int i = 0; i < nItems; i++) {
+ // Get the thread stop info
+ StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
+ const std::string &stop_info_str = stop_info.GetStringRef();
+
+ m_thread_pcs.clear();
+ const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:");
+ if (thread_pcs_pos != std::string::npos) {
+ const size_t start = thread_pcs_pos + strlen(";thread-pcs:");
+ const size_t end = stop_info_str.find(';', start);
+ if (end != std::string::npos) {
+ std::string value = stop_info_str.substr(start, end - start);
+ UpdateThreadPCsFromStopReplyThreadsValue(value);
+ }
}
- if (!m_thread_ids.empty())
- return true;
- }
- else
- {
- // See if we can get the thread IDs from the current stop reply packets
- // that might contain a "threads" key/value pair
-
- // Lock the thread stack while we access it
- //Mutex::Locker stop_stack_lock(m_last_stop_packet_mutex);
- std::unique_lock<std::recursive_mutex> stop_stack_lock(m_last_stop_packet_mutex, std::defer_lock);
- if (stop_stack_lock.try_lock())
- {
- // Get the number of stop packets on the stack
- int nItems = m_stop_packet_stack.size();
- // Iterate over them
- for (int i = 0; i < nItems; i++)
- {
- // Get the thread stop info
- StringExtractorGDBRemote &stop_info = m_stop_packet_stack[i];
- const std::string &stop_info_str = stop_info.GetStringRef();
-
- m_thread_pcs.clear();
- const size_t thread_pcs_pos = stop_info_str.find(";thread-pcs:");
- if (thread_pcs_pos != std::string::npos)
- {
- const size_t start = thread_pcs_pos + strlen(";thread-pcs:");
- const size_t end = stop_info_str.find(';', start);
- if (end != std::string::npos)
- {
- std::string value = stop_info_str.substr(start, end - start);
- UpdateThreadPCsFromStopReplyThreadsValue(value);
- }
- }
- const size_t threads_pos = stop_info_str.find(";threads:");
- if (threads_pos != std::string::npos)
- {
- const size_t start = threads_pos + strlen(";threads:");
- const size_t end = stop_info_str.find(';', start);
- if (end != std::string::npos)
- {
- std::string value = stop_info_str.substr(start, end - start);
- if (UpdateThreadIDsFromStopReplyThreadsValue(value))
- return true;
- }
- }
- }
+ const size_t threads_pos = stop_info_str.find(";threads:");
+ if (threads_pos != std::string::npos) {
+ const size_t start = threads_pos + strlen(";threads:");
+ const size_t end = stop_info_str.find(';', start);
+ if (end != std::string::npos) {
+ std::string value = stop_info_str.substr(start, end - start);
+ if (UpdateThreadIDsFromStopReplyThreadsValue(value))
+ return true;
+ }
}
+ }
}
+ }
- bool sequence_mutex_unavailable = false;
- m_gdb_comm.GetCurrentThreadIDs (m_thread_ids, sequence_mutex_unavailable);
- if (sequence_mutex_unavailable)
- {
- return false; // We just didn't get the list
- }
- return true;
+ bool sequence_mutex_unavailable = false;
+ m_gdb_comm.GetCurrentThreadIDs(m_thread_ids, sequence_mutex_unavailable);
+ if (sequence_mutex_unavailable) {
+ return false; // We just didn't get the list
+ }
+ return true;
}
-bool
-ProcessGDBRemote::UpdateThreadList (ThreadList &old_thread_list, ThreadList &new_thread_list)
-{
- // locker will keep a mutex locked until it goes out of scope
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_THREAD));
- if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
- log->Printf ("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__, GetID());
-
- size_t num_thread_ids = m_thread_ids.size();
- // The "m_thread_ids" thread ID list should always be updated after each stop
- // reply packet, but in case it isn't, update it here.
- if (num_thread_ids == 0)
- {
- if (!UpdateThreadIDList ())
- return false;
- num_thread_ids = m_thread_ids.size();
- }
-
- ThreadList old_thread_list_copy(old_thread_list);
- if (num_thread_ids > 0)
- {
- for (size_t i=0; i<num_thread_ids; ++i)
- {
- tid_t tid = m_thread_ids[i];
- ThreadSP thread_sp (old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
- if (!thread_sp)
- {
- thread_sp.reset (new ThreadGDBRemote (*this, tid));
- if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
- log->Printf(
- "ProcessGDBRemote::%s Making new thread: %p for thread ID: 0x%" PRIx64 ".\n",
- __FUNCTION__, static_cast<void*>(thread_sp.get()),
- thread_sp->GetID());
- }
- else
- {
- if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
- log->Printf(
- "ProcessGDBRemote::%s Found old thread: %p for thread ID: 0x%" PRIx64 ".\n",
- __FUNCTION__, static_cast<void*>(thread_sp.get()),
- thread_sp->GetID());
- }
- // The m_thread_pcs vector has pc values in big-endian order, not target-endian, unlike most
- // of the register read/write packets in gdb-remote protocol.
- // Early in the process startup, we may not yet have set the process ByteOrder so we ignore these;
- // they are a performance improvement over fetching thread register values individually, the
- // method we will fall back to if needed.
- if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() && GetByteOrder() != eByteOrderInvalid)
- {
- ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
- RegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext());
- if (reg_ctx_sp)
- {
- uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber
- (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
- if (pc_regnum != LLDB_INVALID_REGNUM)
- {
- gdb_thread->PrivateSetRegisterValue (pc_regnum, m_thread_pcs[i]);
- }
- }
- }
- new_thread_list.AddThreadSortedByIndexID (thread_sp);
+bool ProcessGDBRemote::UpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) {
+ // locker will keep a mutex locked until it goes out of scope
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_THREAD));
+ if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
+ log->Printf("ProcessGDBRemote::%s (pid = %" PRIu64 ")", __FUNCTION__,
+ GetID());
+
+ size_t num_thread_ids = m_thread_ids.size();
+ // The "m_thread_ids" thread ID list should always be updated after each stop
+ // reply packet, but in case it isn't, update it here.
+ if (num_thread_ids == 0) {
+ if (!UpdateThreadIDList())
+ return false;
+ num_thread_ids = m_thread_ids.size();
+ }
+
+ ThreadList old_thread_list_copy(old_thread_list);
+ if (num_thread_ids > 0) {
+ for (size_t i = 0; i < num_thread_ids; ++i) {
+ tid_t tid = m_thread_ids[i];
+ ThreadSP thread_sp(
+ old_thread_list_copy.RemoveThreadByProtocolID(tid, false));
+ if (!thread_sp) {
+ thread_sp.reset(new ThreadGDBRemote(*this, tid));
+ if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
+ log->Printf("ProcessGDBRemote::%s Making new thread: %p for thread "
+ "ID: 0x%" PRIx64 ".\n",
+ __FUNCTION__, static_cast<void *>(thread_sp.get()),
+ thread_sp->GetID());
+ } else {
+ if (log && log->GetMask().Test(GDBR_LOG_VERBOSE))
+ log->Printf("ProcessGDBRemote::%s Found old thread: %p for thread "
+ "ID: 0x%" PRIx64 ".\n",
+ __FUNCTION__, static_cast<void *>(thread_sp.get()),
+ thread_sp->GetID());
+ }
+ // The m_thread_pcs vector has pc values in big-endian order, not
+ // target-endian, unlike most
+ // of the register read/write packets in gdb-remote protocol.
+ // Early in the process startup, we may not yet have set the process
+ // ByteOrder so we ignore these;
+ // they are a performance improvement over fetching thread register values
+ // individually, the
+ // method we will fall back to if needed.
+ if (m_thread_ids.size() == m_thread_pcs.size() && thread_sp.get() &&
+ GetByteOrder() != eByteOrderInvalid) {
+ ThreadGDBRemote *gdb_thread =
+ static_cast<ThreadGDBRemote *>(thread_sp.get());
+ RegisterContextSP reg_ctx_sp(thread_sp->GetRegisterContext());
+ if (reg_ctx_sp) {
+ uint32_t pc_regnum = reg_ctx_sp->ConvertRegisterKindToRegisterNumber(
+ eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
+ if (pc_regnum != LLDB_INVALID_REGNUM) {
+ gdb_thread->PrivateSetRegisterValue(pc_regnum, m_thread_pcs[i]);
+ }
}
+ }
+ new_thread_list.AddThreadSortedByIndexID(thread_sp);
}
+ }
- // Whatever that is left in old_thread_list_copy are not
- // present in new_thread_list. Remove non-existent threads from internal id table.
- size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
- for (size_t i=0; i<old_num_thread_ids; i++)
- {
- ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex (i, false));
- if (old_thread_sp)
- {
- lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID();
- m_thread_id_to_index_id_map.erase(old_thread_id);
- }
+ // Whatever that is left in old_thread_list_copy are not
+ // present in new_thread_list. Remove non-existent threads from internal id
+ // table.
+ size_t old_num_thread_ids = old_thread_list_copy.GetSize(false);
+ for (size_t i = 0; i < old_num_thread_ids; i++) {
+ ThreadSP old_thread_sp(old_thread_list_copy.GetThreadAtIndex(i, false));
+ if (old_thread_sp) {
+ lldb::tid_t old_thread_id = old_thread_sp->GetProtocolID();
+ m_thread_id_to_index_id_map.erase(old_thread_id);
}
+ }
- return true;
+ return true;
}
-
-bool
-ProcessGDBRemote::GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp)
-{
- // See if we got thread stop infos for all threads via the "jThreadsInfo" packet
- if (thread_infos_sp)
- {
- StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();
- if (thread_infos)
- {
- lldb::tid_t tid;
- const size_t n = thread_infos->GetSize();
- for (size_t i=0; i<n; ++i)
- {
- StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary();
- if (thread_dict)
- {
- if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>("tid", tid, LLDB_INVALID_THREAD_ID))
- {
- if (tid == thread->GetID())
- return (bool)SetThreadStopInfo(thread_dict);
- }
- }
- }
+bool ProcessGDBRemote::GetThreadStopInfoFromJSON(
+ ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp) {
+ // See if we got thread stop infos for all threads via the "jThreadsInfo"
+ // packet
+ if (thread_infos_sp) {
+ StructuredData::Array *thread_infos = thread_infos_sp->GetAsArray();
+ if (thread_infos) {
+ lldb::tid_t tid;
+ const size_t n = thread_infos->GetSize();
+ for (size_t i = 0; i < n; ++i) {
+ StructuredData::Dictionary *thread_dict =
+ thread_infos->GetItemAtIndex(i)->GetAsDictionary();
+ if (thread_dict) {
+ if (thread_dict->GetValueForKeyAsInteger<lldb::tid_t>(
+ "tid", tid, LLDB_INVALID_THREAD_ID)) {
+ if (tid == thread->GetID())
+ return (bool)SetThreadStopInfo(thread_dict);
+ }
}
+ }
}
- return false;
+ }
+ return false;
}
-bool
-ProcessGDBRemote::CalculateThreadStopInfo (ThreadGDBRemote *thread)
-{
- // See if we got thread stop infos for all threads via the "jThreadsInfo" packet
- if (GetThreadStopInfoFromJSON (thread, m_jthreadsinfo_sp))
- return true;
+bool ProcessGDBRemote::CalculateThreadStopInfo(ThreadGDBRemote *thread) {
+ // See if we got thread stop infos for all threads via the "jThreadsInfo"
+ // packet
+ if (GetThreadStopInfoFromJSON(thread, m_jthreadsinfo_sp))
+ return true;
- // See if we got thread stop info for any threads valid stop info reasons threads
- // via the "jstopinfo" packet stop reply packet key/value pair?
- if (m_jstopinfo_sp)
- {
- // If we have "jstopinfo" then we have stop descriptions for all threads
- // that have stop reasons, and if there is no entry for a thread, then
- // it has no stop reason.
- thread->GetRegisterContext()->InvalidateIfNeeded(true);
- if (!GetThreadStopInfoFromJSON (thread, m_jstopinfo_sp))
- {
- thread->SetStopInfo (StopInfoSP());
- }
- return true;
+ // See if we got thread stop info for any threads valid stop info reasons
+ // threads
+ // via the "jstopinfo" packet stop reply packet key/value pair?
+ if (m_jstopinfo_sp) {
+ // If we have "jstopinfo" then we have stop descriptions for all threads
+ // that have stop reasons, and if there is no entry for a thread, then
+ // it has no stop reason.
+ thread->GetRegisterContext()->InvalidateIfNeeded(true);
+ if (!GetThreadStopInfoFromJSON(thread, m_jstopinfo_sp)) {
+ thread->SetStopInfo(StopInfoSP());
}
+ return true;
+ }
- // Fall back to using the qThreadStopInfo packet
- StringExtractorGDBRemote stop_packet;
- if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet))
- return SetThreadStopInfo (stop_packet) == eStateStopped;
- return false;
+ // Fall back to using the qThreadStopInfo packet
+ StringExtractorGDBRemote stop_packet;
+ if (GetGDBRemote().GetThreadStopInfo(thread->GetProtocolID(), stop_packet))
+ return SetThreadStopInfo(stop_packet) == eStateStopped;
+ return false;
}
-
-ThreadSP
-ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
- ExpeditedRegisterMap &expedited_register_map,
- uint8_t signo,
- const std::string &thread_name,
- const std::string &reason,
- const std::string &description,
- uint32_t exc_type,
- const std::vector<addr_t> &exc_data,
- addr_t thread_dispatch_qaddr,
- bool queue_vars_valid, // Set to true if queue_name, queue_kind and queue_serial are valid
- LazyBool associated_with_dispatch_queue,
- addr_t dispatch_queue_t,
- std::string &queue_name,
- QueueKind queue_kind,
- uint64_t queue_serial)
-{
- ThreadSP thread_sp;
- if (tid != LLDB_INVALID_THREAD_ID)
- {
- // Scope for "locker" below
- {
- // m_thread_list_real does have its own mutex, but we need to
- // hold onto the mutex between the call to m_thread_list_real.FindThreadByID(...)
- // and the m_thread_list_real.AddThread(...) so it doesn't change on us
- std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
- thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false);
-
- if (!thread_sp)
- {
- // Create the thread if we need to
- thread_sp.reset (new ThreadGDBRemote (*this, tid));
- m_thread_list_real.AddThread(thread_sp);
+ThreadSP ProcessGDBRemote::SetThreadStopInfo(
+ lldb::tid_t tid, ExpeditedRegisterMap &expedited_register_map,
+ uint8_t signo, const std::string &thread_name, const std::string &reason,
+ const std::string &description, uint32_t exc_type,
+ const std::vector<addr_t> &exc_data, addr_t thread_dispatch_qaddr,
+ bool queue_vars_valid, // Set to true if queue_name, queue_kind and
+ // queue_serial are valid
+ LazyBool associated_with_dispatch_queue, addr_t dispatch_queue_t,
+ std::string &queue_name, QueueKind queue_kind, uint64_t queue_serial) {
+ ThreadSP thread_sp;
+ if (tid != LLDB_INVALID_THREAD_ID) {
+ // Scope for "locker" below
+ {
+ // m_thread_list_real does have its own mutex, but we need to
+ // hold onto the mutex between the call to
+ // m_thread_list_real.FindThreadByID(...)
+ // and the m_thread_list_real.AddThread(...) so it doesn't change on us
+ std::lock_guard<std::recursive_mutex> guard(
+ m_thread_list_real.GetMutex());
+ thread_sp = m_thread_list_real.FindThreadByProtocolID(tid, false);
+
+ if (!thread_sp) {
+ // Create the thread if we need to
+ thread_sp.reset(new ThreadGDBRemote(*this, tid));
+ m_thread_list_real.AddThread(thread_sp);
+ }
+ }
+
+ if (thread_sp) {
+ ThreadGDBRemote *gdb_thread =
+ static_cast<ThreadGDBRemote *>(thread_sp.get());
+ gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true);
+
+ for (const auto &pair : expedited_register_map) {
+ StringExtractor reg_value_extractor;
+ reg_value_extractor.GetStringRef() = pair.second;
+ DataBufferSP buffer_sp(new DataBufferHeap(
+ reg_value_extractor.GetStringRef().size() / 2, 0));
+ reg_value_extractor.GetHexBytes(buffer_sp->GetData(), '\xcc');
+ gdb_thread->PrivateSetRegisterValue(pair.first, buffer_sp->GetData());
+ }
+
+ thread_sp->SetName(thread_name.empty() ? NULL : thread_name.c_str());
+
+ gdb_thread->SetThreadDispatchQAddr(thread_dispatch_qaddr);
+ // Check if the GDB server was able to provide the queue name, kind and
+ // serial number
+ if (queue_vars_valid)
+ gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind,
+ queue_serial, dispatch_queue_t,
+ associated_with_dispatch_queue);
+ else
+ gdb_thread->ClearQueueInfo();
+
+ gdb_thread->SetAssociatedWithLibdispatchQueue(
+ associated_with_dispatch_queue);
+
+ if (dispatch_queue_t != LLDB_INVALID_ADDRESS)
+ gdb_thread->SetQueueLibdispatchQueueAddress(dispatch_queue_t);
+
+ // Make sure we update our thread stop reason just once
+ if (!thread_sp->StopInfoIsUpToDate()) {
+ thread_sp->SetStopInfo(StopInfoSP());
+ // If there's a memory thread backed by this thread, we need to use it
+ // to calcualte StopInfo.
+ ThreadSP memory_thread_sp =
+ m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID());
+ if (memory_thread_sp)
+ thread_sp = memory_thread_sp;
+
+ if (exc_type != 0) {
+ const size_t exc_data_size = exc_data.size();
+
+ thread_sp->SetStopInfo(
+ StopInfoMachException::CreateStopReasonWithMachException(
+ *thread_sp, exc_type, exc_data_size,
+ exc_data_size >= 1 ? exc_data[0] : 0,
+ exc_data_size >= 2 ? exc_data[1] : 0,
+ exc_data_size >= 3 ? exc_data[2] : 0));
+ } else {
+ bool handled = false;
+ bool did_exec = false;
+ if (!reason.empty()) {
+ if (reason.compare("trace") == 0) {
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()
+ ->GetBreakpointSiteList()
+ .FindByAddress(pc);
+
+ // If the current pc is a breakpoint site then the StopInfo should
+ // be set to Breakpoint
+ // Otherwise, it will be set to Trace.
+ if (bp_site_sp &&
+ bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread_sp, bp_site_sp->GetID()));
+ } else
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonToTrace(*thread_sp));
+ handled = true;
+ } else if (reason.compare("breakpoint") == 0) {
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()
+ ->GetBreakpointSiteList()
+ .FindByAddress(pc);
+ if (bp_site_sp) {
+ // If the breakpoint is for this thread, then we'll report the
+ // hit, but if it is for another thread,
+ // we can just report no reason. We don't need to worry about
+ // stepping over the breakpoint here, that
+ // will be taken care of when the thread resumes and notices
+ // that there's a breakpoint under the pc.
+ handled = true;
+ if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread_sp, bp_site_sp->GetID()));
+ } else {
+ StopInfoSP invalid_stop_info_sp;
+ thread_sp->SetStopInfo(invalid_stop_info_sp);
+ }
+ }
+ } else if (reason.compare("trap") == 0) {
+ // Let the trap just use the standard signal stop reason below...
+ } else if (reason.compare("watchpoint") == 0) {
+ StringExtractor desc_extractor(description.c_str());
+ addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
+ uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
+ addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
+ watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
+ if (wp_addr != LLDB_INVALID_ADDRESS) {
+ WatchpointSP wp_sp;
+ ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
+ if ((core >= ArchSpec::kCore_mips_first &&
+ core <= ArchSpec::kCore_mips_last) ||
+ (core >= ArchSpec::eCore_arm_generic &&
+ core <= ArchSpec::eCore_arm_aarch64))
+ wp_sp = GetTarget().GetWatchpointList().FindByAddress(
+ wp_hit_addr);
+ if (!wp_sp)
+ wp_sp =
+ GetTarget().GetWatchpointList().FindByAddress(wp_addr);
+ if (wp_sp) {
+ wp_sp->SetHardwareIndex(wp_index);
+ watch_id = wp_sp->GetID();
+ }
+ }
+ if (watch_id == LLDB_INVALID_WATCH_ID) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(
+ GDBR_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf("failed to find watchpoint");
+ }
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithWatchpointID(
+ *thread_sp, watch_id, wp_hit_addr));
+ handled = true;
+ } else if (reason.compare("exception") == 0) {
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(
+ *thread_sp, description.c_str()));
+ handled = true;
+ } else if (reason.compare("exec") == 0) {
+ did_exec = true;
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithExec(*thread_sp));
+ handled = true;
}
- }
-
- if (thread_sp)
- {
- ThreadGDBRemote *gdb_thread = static_cast<ThreadGDBRemote *> (thread_sp.get());
- gdb_thread->GetRegisterContext()->InvalidateIfNeeded(true);
-
- for (const auto &pair : expedited_register_map)
- {
- StringExtractor reg_value_extractor;
- reg_value_extractor.GetStringRef() = pair.second;
- gdb_thread->PrivateSetRegisterValue (pair.first, reg_value_extractor);
+ } else if (!signo) {
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC();
+ lldb::BreakpointSiteSP bp_site_sp =
+ thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(
+ pc);
+
+ // If the current pc is a breakpoint site then the StopInfo should
+ // be set to Breakpoint
+ // even though the remote stub did not set it as such. This can
+ // happen when
+ // the thread is involuntarily interrupted (e.g. due to stops on
+ // other
+ // threads) just as it is about to execute the breakpoint
+ // instruction.
+ if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread_sp, bp_site_sp->GetID()));
+ handled = true;
}
-
- thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str());
-
- gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr);
- // Check if the GDB server was able to provide the queue name, kind and serial number
- if (queue_vars_valid)
- gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial, dispatch_queue_t, associated_with_dispatch_queue);
- else
- gdb_thread->ClearQueueInfo();
-
- gdb_thread->SetAssociatedWithLibdispatchQueue (associated_with_dispatch_queue);
-
- if (dispatch_queue_t != LLDB_INVALID_ADDRESS)
- gdb_thread->SetQueueLibdispatchQueueAddress (dispatch_queue_t);
-
- // Make sure we update our thread stop reason just once
- if (!thread_sp->StopInfoIsUpToDate())
- {
- thread_sp->SetStopInfo (StopInfoSP());
- // If there's a memory thread backed by this thread, we need to use it to calcualte StopInfo.
- ThreadSP memory_thread_sp = m_thread_list.FindThreadByProtocolID(thread_sp->GetProtocolID());
- if (memory_thread_sp)
- thread_sp = memory_thread_sp;
-
- if (exc_type != 0)
- {
- const size_t exc_data_size = exc_data.size();
-
- thread_sp->SetStopInfo (StopInfoMachException::CreateStopReasonWithMachException (*thread_sp,
- exc_type,
- exc_data_size,
- exc_data_size >= 1 ? exc_data[0] : 0,
- exc_data_size >= 2 ? exc_data[1] : 0,
- exc_data_size >= 3 ? exc_data[2] : 0));
+ }
+
+ if (!handled && signo && did_exec == false) {
+ if (signo == SIGTRAP) {
+ // Currently we are going to assume SIGTRAP means we are either
+ // hitting a breakpoint or hardware single stepping.
+ handled = true;
+ addr_t pc = thread_sp->GetRegisterContext()->GetPC() +
+ m_breakpoint_pc_offset;
+ lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()
+ ->GetBreakpointSiteList()
+ .FindByAddress(pc);
+
+ if (bp_site_sp) {
+ // If the breakpoint is for this thread, then we'll report the
+ // hit, but if it is for another thread,
+ // we can just report no reason. We don't need to worry about
+ // stepping over the breakpoint here, that
+ // will be taken care of when the thread resumes and notices
+ // that there's a breakpoint under the pc.
+ if (bp_site_sp->ValidForThisThread(thread_sp.get())) {
+ if (m_breakpoint_pc_offset != 0)
+ thread_sp->GetRegisterContext()->SetPC(pc);
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonWithBreakpointSiteID(
+ *thread_sp, bp_site_sp->GetID()));
+ } else {
+ StopInfoSP invalid_stop_info_sp;
+ thread_sp->SetStopInfo(invalid_stop_info_sp);
}
+ } else {
+ // If we were stepping then assume the stop was the result of
+ // the trace. If we were
+ // not stepping then report the SIGTRAP.
+ // FIXME: We are still missing the case where we single step
+ // over a trap instruction.
+ if (thread_sp->GetTemporaryResumeState() == eStateStepping)
+ thread_sp->SetStopInfo(
+ StopInfo::CreateStopReasonToTrace(*thread_sp));
else
- {
- bool handled = false;
- bool did_exec = false;
- if (!reason.empty())
- {
- if (reason.compare("trace") == 0)
- {
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
- lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
-
- // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint
- // Otherwise, it will be set to Trace.
- if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get()))
- {
- thread_sp->SetStopInfo(
- StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID()));
- }
- else
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
- handled = true;
- }
- else if (reason.compare("breakpoint") == 0)
- {
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
- lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
- if (bp_site_sp)
- {
- // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
- handled = true;
- if (bp_site_sp->ValidForThisThread (thread_sp.get()))
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
- }
- else
- {
- StopInfoSP invalid_stop_info_sp;
- thread_sp->SetStopInfo (invalid_stop_info_sp);
- }
- }
- }
- else if (reason.compare("trap") == 0)
- {
- // Let the trap just use the standard signal stop reason below...
- }
- else if (reason.compare("watchpoint") == 0)
- {
- StringExtractor desc_extractor(description.c_str());
- addr_t wp_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
- uint32_t wp_index = desc_extractor.GetU32(LLDB_INVALID_INDEX32);
- addr_t wp_hit_addr = desc_extractor.GetU64(LLDB_INVALID_ADDRESS);
- watch_id_t watch_id = LLDB_INVALID_WATCH_ID;
- if (wp_addr != LLDB_INVALID_ADDRESS)
- {
- WatchpointSP wp_sp;
- ArchSpec::Core core = GetTarget().GetArchitecture().GetCore();
- if ((core >= ArchSpec::kCore_mips_first && core <= ArchSpec::kCore_mips_last) ||
- (core >= ArchSpec::eCore_arm_generic && core <= ArchSpec::eCore_arm_aarch64))
- wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_hit_addr);
- if (!wp_sp)
- wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
- if (wp_sp)
- {
- wp_sp->SetHardwareIndex(wp_index);
- watch_id = wp_sp->GetID();
- }
- }
- if (watch_id == LLDB_INVALID_WATCH_ID)
- {
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_WATCHPOINTS));
- if (log) log->Printf ("failed to find watchpoint");
- }
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithWatchpointID (*thread_sp, watch_id, wp_hit_addr));
- handled = true;
- }
- else if (reason.compare("exception") == 0)
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException(*thread_sp, description.c_str()));
- handled = true;
- }
- else if (reason.compare("exec") == 0)
- {
- did_exec = true;
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithExec(*thread_sp));
- handled = true;
- }
- }
- else if (!signo)
- {
- addr_t pc = thread_sp->GetRegisterContext()->GetPC();
- lldb::BreakpointSiteSP bp_site_sp =
- thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
-
- // If the current pc is a breakpoint site then the StopInfo should be set to Breakpoint
- // even though the remote stub did not set it as such. This can happen when
- // the thread is involuntarily interrupted (e.g. due to stops on other
- // threads) just as it is about to execute the breakpoint instruction.
- if (bp_site_sp && bp_site_sp->ValidForThisThread(thread_sp.get()))
- {
- thread_sp->SetStopInfo(
- StopInfo::CreateStopReasonWithBreakpointSiteID(*thread_sp, bp_site_sp->GetID()));
- handled = true;
- }
- }
-
- if (!handled && signo && did_exec == false)
- {
- if (signo == SIGTRAP)
- {
- // Currently we are going to assume SIGTRAP means we are either
- // hitting a breakpoint or hardware single stepping.
- handled = true;
- addr_t pc = thread_sp->GetRegisterContext()->GetPC() + m_breakpoint_pc_offset;
- lldb::BreakpointSiteSP bp_site_sp = thread_sp->GetProcess()->GetBreakpointSiteList().FindByAddress(pc);
-
- if (bp_site_sp)
- {
- // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread,
- // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that
- // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc.
- if (bp_site_sp->ValidForThisThread (thread_sp.get()))
- {
- if(m_breakpoint_pc_offset != 0)
- thread_sp->GetRegisterContext()->SetPC(pc);
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithBreakpointSiteID (*thread_sp, bp_site_sp->GetID()));
- }
- else
- {
- StopInfoSP invalid_stop_info_sp;
- thread_sp->SetStopInfo (invalid_stop_info_sp);
- }
- }
- else
- {
- // If we were stepping then assume the stop was the result of the trace. If we were
- // not stepping then report the SIGTRAP.
- // FIXME: We are still missing the case where we single step over a trap instruction.
- if (thread_sp->GetTemporaryResumeState() == eStateStepping)
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonToTrace (*thread_sp));
- else
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal(*thread_sp, signo, description.c_str()));
- }
- }
- if (!handled)
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithSignal (*thread_sp, signo, description.c_str()));
- }
-
- if (!description.empty())
- {
- lldb::StopInfoSP stop_info_sp (thread_sp->GetStopInfo ());
- if (stop_info_sp)
- {
- const char *stop_info_desc = stop_info_sp->GetDescription();
- if (!stop_info_desc || !stop_info_desc[0])
- stop_info_sp->SetDescription (description.c_str());
- }
- else
- {
- thread_sp->SetStopInfo (StopInfo::CreateStopReasonWithException (*thread_sp, description.c_str()));
- }
- }
- }
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal(
+ *thread_sp, signo, description.c_str()));
+ }
}
+ if (!handled)
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithSignal(
+ *thread_sp, signo, description.c_str()));
+ }
+
+ if (!description.empty()) {
+ lldb::StopInfoSP stop_info_sp(thread_sp->GetStopInfo());
+ if (stop_info_sp) {
+ const char *stop_info_desc = stop_info_sp->GetDescription();
+ if (!stop_info_desc || !stop_info_desc[0])
+ stop_info_sp->SetDescription(description.c_str());
+ } else {
+ thread_sp->SetStopInfo(StopInfo::CreateStopReasonWithException(
+ *thread_sp, description.c_str()));
+ }
+ }
}
+ }
}
- return thread_sp;
+ }
+ return thread_sp;
}
lldb::ThreadSP
-ProcessGDBRemote::SetThreadStopInfo (StructuredData::Dictionary *thread_dict)
-{
- static ConstString g_key_tid("tid");
- static ConstString g_key_name("name");
- static ConstString g_key_reason("reason");
- static ConstString g_key_metype("metype");
- static ConstString g_key_medata("medata");
- static ConstString g_key_qaddr("qaddr");
- static ConstString g_key_dispatch_queue_t("dispatch_queue_t");
- static ConstString g_key_associated_with_dispatch_queue("associated_with_dispatch_queue");
- static ConstString g_key_queue_name("qname");
- static ConstString g_key_queue_kind("qkind");
- static ConstString g_key_queue_serial_number("qserialnum");
- static ConstString g_key_registers("registers");
- static ConstString g_key_memory("memory");
- static ConstString g_key_address("address");
- static ConstString g_key_bytes("bytes");
- static ConstString g_key_description("description");
- static ConstString g_key_signal("signal");
+ProcessGDBRemote::SetThreadStopInfo(StructuredData::Dictionary *thread_dict) {
+ static ConstString g_key_tid("tid");
+ static ConstString g_key_name("name");
+ static ConstString g_key_reason("reason");
+ static ConstString g_key_metype("metype");
+ static ConstString g_key_medata("medata");
+ static ConstString g_key_qaddr("qaddr");
+ static ConstString g_key_dispatch_queue_t("dispatch_queue_t");
+ static ConstString g_key_associated_with_dispatch_queue(
+ "associated_with_dispatch_queue");
+ static ConstString g_key_queue_name("qname");
+ static ConstString g_key_queue_kind("qkind");
+ static ConstString g_key_queue_serial_number("qserialnum");
+ static ConstString g_key_registers("registers");
+ static ConstString g_key_memory("memory");
+ static ConstString g_key_address("address");
+ static ConstString g_key_bytes("bytes");
+ static ConstString g_key_description("description");
+ static ConstString g_key_signal("signal");
+
+ // Stop with signal and thread info
+ lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+ uint8_t signo = 0;
+ std::string value;
+ std::string thread_name;
+ std::string reason;
+ std::string description;
+ uint32_t exc_type = 0;
+ std::vector<addr_t> exc_data;
+ addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
+ ExpeditedRegisterMap expedited_register_map;
+ bool queue_vars_valid = false;
+ addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
+ std::string queue_name;
+ QueueKind queue_kind = eQueueKindUnknown;
+ uint64_t queue_serial_number = 0;
+ // Iterate through all of the thread dictionary key/value pairs from the
+ // structured data dictionary
+
+ thread_dict->ForEach([this, &tid, &expedited_register_map, &thread_name,
+ &signo, &reason, &description, &exc_type, &exc_data,
+ &thread_dispatch_qaddr, &queue_vars_valid,
+ &associated_with_dispatch_queue, &dispatch_queue_t,
+ &queue_name, &queue_kind, &queue_serial_number](
+ ConstString key,
+ StructuredData::Object *object) -> bool {
+ if (key == g_key_tid) {
+ // thread in big endian hex
+ tid = object->GetIntegerValue(LLDB_INVALID_THREAD_ID);
+ } else if (key == g_key_metype) {
+ // exception type in big endian hex
+ exc_type = object->GetIntegerValue(0);
+ } else if (key == g_key_medata) {
+ // exception data in big endian hex
+ StructuredData::Array *array = object->GetAsArray();
+ if (array) {
+ array->ForEach([&exc_data](StructuredData::Object *object) -> bool {
+ exc_data.push_back(object->GetIntegerValue());
+ return true; // Keep iterating through all array items
+ });
+ }
+ } else if (key == g_key_name) {
+ thread_name = object->GetStringValue();
+ } else if (key == g_key_qaddr) {
+ thread_dispatch_qaddr = object->GetIntegerValue(LLDB_INVALID_ADDRESS);
+ } else if (key == g_key_queue_name) {
+ queue_vars_valid = true;
+ queue_name = object->GetStringValue();
+ } else if (key == g_key_queue_kind) {
+ std::string queue_kind_str = object->GetStringValue();
+ if (queue_kind_str == "serial") {
+ queue_vars_valid = true;
+ queue_kind = eQueueKindSerial;
+ } else if (queue_kind_str == "concurrent") {
+ queue_vars_valid = true;
+ queue_kind = eQueueKindConcurrent;
+ }
+ } else if (key == g_key_queue_serial_number) {
+ queue_serial_number = object->GetIntegerValue(0);
+ if (queue_serial_number != 0)
+ queue_vars_valid = true;
+ } else if (key == g_key_dispatch_queue_t) {
+ dispatch_queue_t = object->GetIntegerValue(0);
+ if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS)
+ queue_vars_valid = true;
+ } else if (key == g_key_associated_with_dispatch_queue) {
+ queue_vars_valid = true;
+ bool associated = object->GetBooleanValue();
+ if (associated)
+ associated_with_dispatch_queue = eLazyBoolYes;
+ else
+ associated_with_dispatch_queue = eLazyBoolNo;
+ } else if (key == g_key_reason) {
+ reason = object->GetStringValue();
+ } else if (key == g_key_description) {
+ description = object->GetStringValue();
+ } else if (key == g_key_registers) {
+ StructuredData::Dictionary *registers_dict = object->GetAsDictionary();
+
+ if (registers_dict) {
+ registers_dict->ForEach(
+ [&expedited_register_map](ConstString key,
+ StructuredData::Object *object) -> bool {
+ const uint32_t reg =
+ StringConvert::ToUInt32(key.GetCString(), UINT32_MAX, 10);
+ if (reg != UINT32_MAX)
+ expedited_register_map[reg] = object->GetStringValue();
+ return true; // Keep iterating through all array items
+ });
+ }
+ } else if (key == g_key_memory) {
+ StructuredData::Array *array = object->GetAsArray();
+ if (array) {
+ array->ForEach([this](StructuredData::Object *object) -> bool {
+ StructuredData::Dictionary *mem_cache_dict =
+ object->GetAsDictionary();
+ if (mem_cache_dict) {
+ lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS;
+ if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>(
+ "address", mem_cache_addr)) {
+ if (mem_cache_addr != LLDB_INVALID_ADDRESS) {
+ StringExtractor bytes;
+ if (mem_cache_dict->GetValueForKeyAsString(
+ "bytes", bytes.GetStringRef())) {
+ bytes.SetFilePos(0);
+
+ const size_t byte_size = bytes.GetStringRef().size() / 2;
+ DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
+ const size_t bytes_copied =
+ bytes.GetHexBytes(data_buffer_sp->GetData(), 0);
+ if (bytes_copied == byte_size)
+ m_memory_cache.AddL1CacheData(mem_cache_addr,
+ data_buffer_sp);
+ }
+ }
+ }
+ }
+ return true; // Keep iterating through all array items
+ });
+ }
+
+ } else if (key == g_key_signal)
+ signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);
+ return true; // Keep iterating through all dictionary key/value pairs
+ });
+
+ return SetThreadStopInfo(tid, expedited_register_map, signo, thread_name,
+ reason, description, exc_type, exc_data,
+ thread_dispatch_qaddr, queue_vars_valid,
+ associated_with_dispatch_queue, dispatch_queue_t,
+ queue_name, queue_kind, queue_serial_number);
+}
+StateType ProcessGDBRemote::SetThreadStopInfo(StringExtractor &stop_packet) {
+ stop_packet.SetFilePos(0);
+ const char stop_type = stop_packet.GetChar();
+ switch (stop_type) {
+ case 'T':
+ case 'S': {
+ // This is a bit of a hack, but is is required. If we did exec, we
+ // need to clear our thread lists and also know to rebuild our dynamic
+ // register info before we lookup and threads and populate the expedited
+ // register values so we need to know this right away so we can cleanup
+ // and update our registers.
+ const uint32_t stop_id = GetStopID();
+ if (stop_id == 0) {
+ // Our first stop, make sure we have a process ID, and also make
+ // sure we know about our registers
+ if (GetID() == LLDB_INVALID_PROCESS_ID) {
+ lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ SetID(pid);
+ }
+ BuildDynamicRegisterInfo(true);
+ }
// Stop with signal and thread info
lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- uint8_t signo = 0;
- std::string value;
+ const uint8_t signo = stop_packet.GetHexU8();
+ llvm::StringRef key;
+ llvm::StringRef value;
std::string thread_name;
std::string reason;
std::string description;
uint32_t exc_type = 0;
std::vector<addr_t> exc_data;
addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
- ExpeditedRegisterMap expedited_register_map;
- bool queue_vars_valid = false;
+ bool queue_vars_valid =
+ false; // says if locals below that start with "queue_" are valid
addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
std::string queue_name;
QueueKind queue_kind = eQueueKindUnknown;
uint64_t queue_serial_number = 0;
- // Iterate through all of the thread dictionary key/value pairs from the structured data dictionary
-
- thread_dict->ForEach([this,
- &tid,
- &expedited_register_map,
- &thread_name,
- &signo,
- &reason,
- &description,
- &exc_type,
- &exc_data,
- &thread_dispatch_qaddr,
- &queue_vars_valid,
- &associated_with_dispatch_queue,
- &dispatch_queue_t,
- &queue_name,
- &queue_kind,
- &queue_serial_number]
- (ConstString key, StructuredData::Object* object) -> bool
- {
- if (key == g_key_tid)
- {
- // thread in big endian hex
- tid = object->GetIntegerValue(LLDB_INVALID_THREAD_ID);
- }
- else if (key == g_key_metype)
- {
- // exception type in big endian hex
- exc_type = object->GetIntegerValue(0);
- }
- else if (key == g_key_medata)
- {
- // exception data in big endian hex
- StructuredData::Array *array = object->GetAsArray();
- if (array)
- {
- array->ForEach([&exc_data](StructuredData::Object* object) -> bool {
- exc_data.push_back(object->GetIntegerValue());
- return true; // Keep iterating through all array items
- });
- }
- }
- else if (key == g_key_name)
- {
- thread_name = object->GetStringValue();
- }
- else if (key == g_key_qaddr)
- {
- thread_dispatch_qaddr = object->GetIntegerValue(LLDB_INVALID_ADDRESS);
- }
- else if (key == g_key_queue_name)
- {
- queue_vars_valid = true;
- queue_name = object->GetStringValue();
- }
- else if (key == g_key_queue_kind)
- {
- std::string queue_kind_str = object->GetStringValue();
- if (queue_kind_str == "serial")
- {
- queue_vars_valid = true;
- queue_kind = eQueueKindSerial;
- }
- else if (queue_kind_str == "concurrent")
- {
- queue_vars_valid = true;
- queue_kind = eQueueKindConcurrent;
- }
- }
- else if (key == g_key_queue_serial_number)
- {
- queue_serial_number = object->GetIntegerValue(0);
- if (queue_serial_number != 0)
- queue_vars_valid = true;
- }
- else if (key == g_key_dispatch_queue_t)
- {
- dispatch_queue_t = object->GetIntegerValue(0);
- if (dispatch_queue_t != 0 && dispatch_queue_t != LLDB_INVALID_ADDRESS)
- queue_vars_valid = true;
- }
- else if (key == g_key_associated_with_dispatch_queue)
- {
- queue_vars_valid = true;
- bool associated = object->GetBooleanValue ();
- if (associated)
- associated_with_dispatch_queue = eLazyBoolYes;
- else
- associated_with_dispatch_queue = eLazyBoolNo;
- }
- else if (key == g_key_reason)
- {
- reason = object->GetStringValue();
- }
- else if (key == g_key_description)
- {
- description = object->GetStringValue();
+ ExpeditedRegisterMap expedited_register_map;
+ while (stop_packet.GetNameColonValue(key, value)) {
+ if (key.compare("metype") == 0) {
+ // exception type in big endian hex
+ value.getAsInteger(16, exc_type);
+ } else if (key.compare("medata") == 0) {
+ // exception data in big endian hex
+ uint64_t x;
+ value.getAsInteger(16, x);
+ exc_data.push_back(x);
+ } else if (key.compare("thread") == 0) {
+ // thread in big endian hex
+ if (value.getAsInteger(16, tid))
+ tid = LLDB_INVALID_THREAD_ID;
+ } else if (key.compare("threads") == 0) {
+ std::lock_guard<std::recursive_mutex> guard(
+ m_thread_list_real.GetMutex());
+
+ m_thread_ids.clear();
+ // A comma separated list of all threads in the current
+ // process that includes the thread for this stop reply
+ // packet
+ lldb::tid_t tid;
+ while (!value.empty()) {
+ llvm::StringRef tid_str;
+ std::tie(tid_str, value) = value.split(',');
+ if (tid_str.getAsInteger(16, tid))
+ tid = LLDB_INVALID_THREAD_ID;
+ m_thread_ids.push_back(tid);
}
- else if (key == g_key_registers)
- {
- StructuredData::Dictionary *registers_dict = object->GetAsDictionary();
-
- if (registers_dict)
- {
- registers_dict->ForEach([&expedited_register_map](ConstString key, StructuredData::Object* object) -> bool {
- const uint32_t reg = StringConvert::ToUInt32 (key.GetCString(), UINT32_MAX, 10);
- if (reg != UINT32_MAX)
- expedited_register_map[reg] = object->GetStringValue();
- return true; // Keep iterating through all array items
- });
- }
+ } else if (key.compare("thread-pcs") == 0) {
+ m_thread_pcs.clear();
+ // A comma separated list of all threads in the current
+ // process that includes the thread for this stop reply
+ // packet
+ lldb::addr_t pc;
+ while (!value.empty()) {
+ llvm::StringRef pc_str;
+ std::tie(pc_str, value) = value.split(',');
+ if (pc_str.getAsInteger(16, pc))
+ pc = LLDB_INVALID_ADDRESS;
+ m_thread_pcs.push_back(pc);
}
- else if (key == g_key_memory)
- {
- StructuredData::Array *array = object->GetAsArray();
- if (array)
- {
- array->ForEach([this](StructuredData::Object* object) -> bool {
- StructuredData::Dictionary *mem_cache_dict = object->GetAsDictionary();
- if (mem_cache_dict)
- {
- lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS;
- if (mem_cache_dict->GetValueForKeyAsInteger<lldb::addr_t>("address", mem_cache_addr))
- {
- if (mem_cache_addr != LLDB_INVALID_ADDRESS)
- {
- StringExtractor bytes;
- if (mem_cache_dict->GetValueForKeyAsString("bytes", bytes.GetStringRef()))
- {
- bytes.SetFilePos(0);
-
- const size_t byte_size = bytes.GetStringRef().size()/2;
- DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
- const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetBytes(), byte_size, 0);
- if (bytes_copied == byte_size)
- m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp);
- }
- }
- }
- }
- return true; // Keep iterating through all array items
- });
- }
-
+ } else if (key.compare("jstopinfo") == 0) {
+ StringExtractor json_extractor(value);
+ std::string json;
+ // Now convert the HEX bytes into a string value
+ json_extractor.GetHexByteString(json);
+
+ // This JSON contains thread IDs and thread stop info for all threads.
+ // It doesn't contain expedited registers, memory or queue info.
+ m_jstopinfo_sp = StructuredData::ParseJSON(json);
+ } else if (key.compare("hexname") == 0) {
+ StringExtractor name_extractor(value);
+ std::string name;
+ // Now convert the HEX bytes into a string value
+ name_extractor.GetHexByteString(thread_name);
+ } else if (key.compare("name") == 0) {
+ thread_name = value;
+ } else if (key.compare("qaddr") == 0) {
+ value.getAsInteger(16, thread_dispatch_qaddr);
+ } else if (key.compare("dispatch_queue_t") == 0) {
+ queue_vars_valid = true;
+ value.getAsInteger(16, dispatch_queue_t);
+ } else if (key.compare("qname") == 0) {
+ queue_vars_valid = true;
+ StringExtractor name_extractor(value);
+ // Now convert the HEX bytes into a string value
+ name_extractor.GetHexByteString(queue_name);
+ } else if (key.compare("qkind") == 0) {
+ queue_kind = llvm::StringSwitch<QueueKind>(value)
+ .Case("serial", eQueueKindSerial)
+ .Case("concurrent", eQueueKindConcurrent)
+ .Default(eQueueKindUnknown);
+ queue_vars_valid = queue_kind != eQueueKindUnknown;
+ } else if (key.compare("qserialnum") == 0) {
+ if (!value.getAsInteger(0, queue_serial_number))
+ queue_vars_valid = true;
+ } else if (key.compare("reason") == 0) {
+ reason = value;
+ } else if (key.compare("description") == 0) {
+ StringExtractor desc_extractor(value);
+ // Now convert the HEX bytes into a string value
+ desc_extractor.GetHexByteString(description);
+ } else if (key.compare("memory") == 0) {
+ // Expedited memory. GDB servers can choose to send back expedited
+ // memory
+ // that can populate the L1 memory cache in the process so that things
+ // like
+ // the frame pointer backchain can be expedited. This will help stack
+ // backtracing be more efficient by not having to send as many memory
+ // read
+ // requests down the remote GDB server.
+
+ // Key/value pair format: memory:<addr>=<bytes>;
+ // <addr> is a number whose base will be interpreted by the prefix:
+ // "0x[0-9a-fA-F]+" for hex
+ // "0[0-7]+" for octal
+ // "[1-9]+" for decimal
+ // <bytes> is native endian ASCII hex bytes just like the register
+ // values
+ llvm::StringRef addr_str, bytes_str;
+ std::tie(addr_str, bytes_str) = value.split('=');
+ if (!addr_str.empty() && !bytes_str.empty()) {
+ lldb::addr_t mem_cache_addr = LLDB_INVALID_ADDRESS;
+ if (!addr_str.getAsInteger(0, mem_cache_addr)) {
+ StringExtractor bytes(bytes_str);
+ const size_t byte_size = bytes.GetBytesLeft() / 2;
+ DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
+ const size_t bytes_copied =
+ bytes.GetHexBytes(data_buffer_sp->GetData(), 0);
+ if (bytes_copied == byte_size)
+ m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp);
+ }
}
- else if (key == g_key_signal)
- signo = object->GetIntegerValue(LLDB_INVALID_SIGNAL_NUMBER);
- return true; // Keep iterating through all dictionary key/value pairs
- });
-
- return SetThreadStopInfo (tid,
- expedited_register_map,
- signo,
- thread_name,
- reason,
- description,
- exc_type,
- exc_data,
- thread_dispatch_qaddr,
- queue_vars_valid,
- associated_with_dispatch_queue,
- dispatch_queue_t,
- queue_name,
- queue_kind,
- queue_serial_number);
+ } else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 ||
+ key.compare("awatch") == 0) {
+ // Support standard GDB remote stop reply packet 'TAAwatch:addr'
+ lldb::addr_t wp_addr = LLDB_INVALID_ADDRESS;
+ value.getAsInteger(16, wp_addr);
+
+ WatchpointSP wp_sp =
+ GetTarget().GetWatchpointList().FindByAddress(wp_addr);
+ uint32_t wp_index = LLDB_INVALID_INDEX32;
+
+ if (wp_sp)
+ wp_index = wp_sp->GetHardwareIndex();
+
+ reason = "watchpoint";
+ StreamString ostr;
+ ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index);
+ description = ostr.GetString();
+ } else if (key.compare("library") == 0) {
+ LoadModules();
+ } else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1])) {
+ uint32_t reg = UINT32_MAX;
+ if (!key.getAsInteger(16, reg))
+ expedited_register_map[reg] = std::move(value);
+ }
+ }
+
+ if (tid == LLDB_INVALID_THREAD_ID) {
+ // A thread id may be invalid if the response is old style 'S' packet
+ // which does not provide the
+ // thread information. So update the thread list and choose the first one.
+ UpdateThreadIDList();
+
+ if (!m_thread_ids.empty()) {
+ tid = m_thread_ids.front();
+ }
+ }
+
+ ThreadSP thread_sp = SetThreadStopInfo(
+ tid, expedited_register_map, signo, thread_name, reason, description,
+ exc_type, exc_data, thread_dispatch_qaddr, queue_vars_valid,
+ associated_with_dispatch_queue, dispatch_queue_t, queue_name,
+ queue_kind, queue_serial_number);
+
+ return eStateStopped;
+ } break;
+
+ case 'W':
+ case 'X':
+ // process exited
+ return eStateExited;
+
+ default:
+ break;
+ }
+ return eStateInvalid;
}
-StateType
-ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet)
-{
- stop_packet.SetFilePos (0);
- const char stop_type = stop_packet.GetChar();
- switch (stop_type)
- {
- case 'T':
- case 'S':
- {
- // This is a bit of a hack, but is is required. If we did exec, we
- // need to clear our thread lists and also know to rebuild our dynamic
- // register info before we lookup and threads and populate the expedited
- // register values so we need to know this right away so we can cleanup
- // and update our registers.
- const uint32_t stop_id = GetStopID();
- if (stop_id == 0)
- {
- // Our first stop, make sure we have a process ID, and also make
- // sure we know about our registers
- if (GetID() == LLDB_INVALID_PROCESS_ID)
- {
- lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID ();
- if (pid != LLDB_INVALID_PROCESS_ID)
- SetID (pid);
- }
- BuildDynamicRegisterInfo (true);
- }
- // Stop with signal and thread info
- lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
- const uint8_t signo = stop_packet.GetHexU8();
- std::string key;
- std::string value;
- std::string thread_name;
- std::string reason;
- std::string description;
- uint32_t exc_type = 0;
- std::vector<addr_t> exc_data;
- addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS;
- bool queue_vars_valid = false; // says if locals below that start with "queue_" are valid
- addr_t dispatch_queue_t = LLDB_INVALID_ADDRESS;
- LazyBool associated_with_dispatch_queue = eLazyBoolCalculate;
- std::string queue_name;
- QueueKind queue_kind = eQueueKindUnknown;
- uint64_t queue_serial_number = 0;
- ExpeditedRegisterMap expedited_register_map;
- while (stop_packet.GetNameColonValue(key, value))
- {
- if (key.compare("metype") == 0)
- {
- // exception type in big endian hex
- exc_type = StringConvert::ToUInt32 (value.c_str(), 0, 16);
- }
- else if (key.compare("medata") == 0)
- {
- // exception data in big endian hex
- exc_data.push_back(StringConvert::ToUInt64 (value.c_str(), 0, 16));
- }
- else if (key.compare("thread") == 0)
- {
- // thread in big endian hex
- tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
- }
- else if (key.compare("threads") == 0)
- {
- std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
-
- m_thread_ids.clear();
- // A comma separated list of all threads in the current
- // process that includes the thread for this stop reply
- // packet
- size_t comma_pos;
- lldb::tid_t tid;
- while ((comma_pos = value.find(',')) != std::string::npos)
- {
- value[comma_pos] = '\0';
- // thread in big endian hex
- tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
- if (tid != LLDB_INVALID_THREAD_ID)
- m_thread_ids.push_back (tid);
- value.erase(0, comma_pos + 1);
- }
- tid = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_THREAD_ID, 16);
- if (tid != LLDB_INVALID_THREAD_ID)
- m_thread_ids.push_back (tid);
- }
- else if (key.compare("thread-pcs") == 0)
- {
- m_thread_pcs.clear();
- // A comma separated list of all threads in the current
- // process that includes the thread for this stop reply
- // packet
- size_t comma_pos;
- lldb::addr_t pc;
- while ((comma_pos = value.find(',')) != std::string::npos)
- {
- value[comma_pos] = '\0';
- // thread in big endian hex
- pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
- if (pc != LLDB_INVALID_ADDRESS)
- m_thread_pcs.push_back (pc);
- value.erase(0, comma_pos + 1);
- }
- pc = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
- if (pc != LLDB_INVALID_ADDRESS)
- m_thread_pcs.push_back (pc);
- }
- else if (key.compare("jstopinfo") == 0)
- {
- StringExtractor json_extractor;
- // Swap "value" over into "name_extractor"
- json_extractor.GetStringRef().swap(value);
- // Now convert the HEX bytes into a string value
- json_extractor.GetHexByteString (value);
-
- // This JSON contains thread IDs and thread stop info for all threads.
- // It doesn't contain expedited registers, memory or queue info.
- m_jstopinfo_sp = StructuredData::ParseJSON (value);
- }
- else if (key.compare("hexname") == 0)
- {
- StringExtractor name_extractor;
- // Swap "value" over into "name_extractor"
- name_extractor.GetStringRef().swap(value);
- // Now convert the HEX bytes into a string value
- name_extractor.GetHexByteString (value);
- thread_name.swap (value);
- }
- else if (key.compare("name") == 0)
- {
- thread_name.swap (value);
- }
- else if (key.compare("qaddr") == 0)
- {
- thread_dispatch_qaddr = StringConvert::ToUInt64 (value.c_str(), 0, 16);
- }
- else if (key.compare("dispatch_queue_t") == 0)
- {
- queue_vars_valid = true;
- dispatch_queue_t = StringConvert::ToUInt64 (value.c_str(), 0, 16);
- }
- else if (key.compare("qname") == 0)
- {
- queue_vars_valid = true;
- StringExtractor name_extractor;
- // Swap "value" over into "name_extractor"
- name_extractor.GetStringRef().swap(value);
- // Now convert the HEX bytes into a string value
- name_extractor.GetHexByteString (value);
- queue_name.swap (value);
- }
- else if (key.compare("qkind") == 0)
- {
- if (value == "serial")
- {
- queue_vars_valid = true;
- queue_kind = eQueueKindSerial;
- }
- else if (value == "concurrent")
- {
- queue_vars_valid = true;
- queue_kind = eQueueKindConcurrent;
- }
- }
- else if (key.compare("qserialnum") == 0)
- {
- queue_serial_number = StringConvert::ToUInt64 (value.c_str(), 0, 0);
- if (queue_serial_number != 0)
- queue_vars_valid = true;
- }
- else if (key.compare("reason") == 0)
- {
- reason.swap(value);
- }
- else if (key.compare("description") == 0)
- {
- StringExtractor desc_extractor;
- // Swap "value" over into "name_extractor"
- desc_extractor.GetStringRef().swap(value);
- // Now convert the HEX bytes into a string value
- desc_extractor.GetHexByteString (value);
- description.swap(value);
- }
- else if (key.compare("memory") == 0)
- {
- // Expedited memory. GDB servers can choose to send back expedited memory
- // that can populate the L1 memory cache in the process so that things like
- // the frame pointer backchain can be expedited. This will help stack
- // backtracing be more efficient by not having to send as many memory read
- // requests down the remote GDB server.
-
- // Key/value pair format: memory:<addr>=<bytes>;
- // <addr> is a number whose base will be interpreted by the prefix:
- // "0x[0-9a-fA-F]+" for hex
- // "0[0-7]+" for octal
- // "[1-9]+" for decimal
- // <bytes> is native endian ASCII hex bytes just like the register values
- llvm::StringRef value_ref(value);
- std::pair<llvm::StringRef, llvm::StringRef> pair;
- pair = value_ref.split('=');
- if (!pair.first.empty() && !pair.second.empty())
- {
- std::string addr_str(pair.first.str());
- const lldb::addr_t mem_cache_addr = StringConvert::ToUInt64(addr_str.c_str(), LLDB_INVALID_ADDRESS, 0);
- if (mem_cache_addr != LLDB_INVALID_ADDRESS)
- {
- StringExtractor bytes;
- bytes.GetStringRef() = pair.second.str();
- const size_t byte_size = bytes.GetStringRef().size()/2;
- DataBufferSP data_buffer_sp(new DataBufferHeap(byte_size, 0));
- const size_t bytes_copied = bytes.GetHexBytes (data_buffer_sp->GetBytes(), byte_size, 0);
- if (bytes_copied == byte_size)
- m_memory_cache.AddL1CacheData(mem_cache_addr, data_buffer_sp);
- }
- }
- }
- else if (key.compare("watch") == 0 || key.compare("rwatch") == 0 || key.compare("awatch") == 0)
- {
- // Support standard GDB remote stop reply packet 'TAAwatch:addr'
- lldb::addr_t wp_addr = StringConvert::ToUInt64 (value.c_str(), LLDB_INVALID_ADDRESS, 16);
- WatchpointSP wp_sp = GetTarget().GetWatchpointList().FindByAddress(wp_addr);
- uint32_t wp_index = LLDB_INVALID_INDEX32;
-
- if (wp_sp)
- wp_index = wp_sp->GetHardwareIndex();
-
- reason = "watchpoint";
- StreamString ostr;
- ostr.Printf("%" PRIu64 " %" PRIu32, wp_addr, wp_index);
- description = ostr.GetString().c_str();
- }
- else if (key.compare("library") == 0)
- {
- LoadModules();
- }
- else if (key.size() == 2 && ::isxdigit(key[0]) && ::isxdigit(key[1]))
- {
- uint32_t reg = StringConvert::ToUInt32 (key.c_str(), UINT32_MAX, 16);
- if (reg != UINT32_MAX)
- expedited_register_map[reg] = std::move(value);
- }
- }
-
- if (tid == LLDB_INVALID_THREAD_ID)
- {
- // A thread id may be invalid if the response is old style 'S' packet which does not provide the
- // thread information. So update the thread list and choose the first one.
- UpdateThreadIDList ();
-
- if (!m_thread_ids.empty ())
- {
- tid = m_thread_ids.front ();
- }
- }
-
- ThreadSP thread_sp = SetThreadStopInfo (tid,
- expedited_register_map,
- signo,
- thread_name,
- reason,
- description,
- exc_type,
- exc_data,
- thread_dispatch_qaddr,
- queue_vars_valid,
- associated_with_dispatch_queue,
- dispatch_queue_t,
- queue_name,
- queue_kind,
- queue_serial_number);
-
- return eStateStopped;
- }
- break;
-
- case 'W':
- case 'X':
- // process exited
- return eStateExited;
-
- default:
- break;
- }
- return eStateInvalid;
+void ProcessGDBRemote::RefreshStateAfterStop() {
+ std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
+
+ m_thread_ids.clear();
+ m_thread_pcs.clear();
+ // Set the thread stop info. It might have a "threads" key whose value is
+ // a list of all thread IDs in the current process, so m_thread_ids might
+ // get set.
+
+ // Scope for the lock
+ {
+ // Lock the thread stack while we access it
+ std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
+ // Get the number of stop packets on the stack
+ int nItems = m_stop_packet_stack.size();
+ // Iterate over them
+ for (int i = 0; i < nItems; i++) {
+ // Get the thread stop info
+ StringExtractorGDBRemote stop_info = m_stop_packet_stack[i];
+ // Process thread stop info
+ SetThreadStopInfo(stop_info);
+ }
+ // Clear the thread stop stack
+ m_stop_packet_stack.clear();
+ }
+
+ // Check to see if SetThreadStopInfo() filled in m_thread_ids?
+ if (m_thread_ids.empty()) {
+ // No, we need to fetch the thread list manually
+ UpdateThreadIDList();
+ }
+
+ // If we have queried for a default thread id
+ if (m_initial_tid != LLDB_INVALID_THREAD_ID) {
+ m_thread_list.SetSelectedThreadByID(m_initial_tid);
+ m_initial_tid = LLDB_INVALID_THREAD_ID;
+ }
+
+ // Let all threads recover from stopping and do any clean up based
+ // on the previous thread state (if any).
+ m_thread_list_real.RefreshStateAfterStop();
}
-void
-ProcessGDBRemote::RefreshStateAfterStop ()
-{
- std::lock_guard<std::recursive_mutex> guard(m_thread_list_real.GetMutex());
-
- m_thread_ids.clear();
- m_thread_pcs.clear();
- // Set the thread stop info. It might have a "threads" key whose value is
- // a list of all thread IDs in the current process, so m_thread_ids might
- // get set.
-
- // Scope for the lock
- {
- // Lock the thread stack while we access it
- std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
- // Get the number of stop packets on the stack
- int nItems = m_stop_packet_stack.size();
- // Iterate over them
- for (int i = 0; i < nItems; i++)
- {
- // Get the thread stop info
- StringExtractorGDBRemote stop_info = m_stop_packet_stack[i];
- // Process thread stop info
- SetThreadStopInfo(stop_info);
- }
- // Clear the thread stop stack
- m_stop_packet_stack.clear();
- }
-
- // Check to see if SetThreadStopInfo() filled in m_thread_ids?
- if (m_thread_ids.empty())
- {
- // No, we need to fetch the thread list manually
- UpdateThreadIDList();
- }
-
- // If we have queried for a default thread id
- if (m_initial_tid != LLDB_INVALID_THREAD_ID)
- {
- m_thread_list.SetSelectedThreadByID(m_initial_tid);
- m_initial_tid = LLDB_INVALID_THREAD_ID;
- }
-
- // Let all threads recover from stopping and do any clean up based
- // on the previous thread state (if any).
- m_thread_list_real.RefreshStateAfterStop();
+Error ProcessGDBRemote::DoHalt(bool &caused_stop) {
+ Error error;
+ if (m_public_state.GetValue() == eStateAttaching) {
+ // We are being asked to halt during an attach. We need to just close
+ // our file handle and debugserver will go away, and we can be done...
+ m_gdb_comm.Disconnect();
+ } else
+ caused_stop = m_gdb_comm.Interrupt();
+ return error;
}
-Error
-ProcessGDBRemote::DoHalt (bool &caused_stop)
-{
- Error error;
-
- bool timed_out = false;
- Mutex::Locker locker;
+Error ProcessGDBRemote::DoDetach(bool keep_stopped) {
+ Error error;
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);
- if (m_public_state.GetValue() == eStateAttaching)
- {
- // We are being asked to halt during an attach. We need to just close
- // our file handle and debugserver will go away, and we can be done...
- m_gdb_comm.Disconnect();
- }
+ error = m_gdb_comm.Detach(keep_stopped);
+ if (log) {
+ if (error.Success())
+ log->PutCString(
+ "ProcessGDBRemote::DoDetach() detach packet sent successfully");
else
- {
- if (!m_gdb_comm.SendInterrupt (locker, 2, timed_out))
- {
- if (timed_out)
- error.SetErrorString("timed out sending interrupt packet");
- else
- error.SetErrorString("unknown error sending interrupt packet");
- }
+ log->Printf("ProcessGDBRemote::DoDetach() detach packet send failed: %s",
+ error.AsCString() ? error.AsCString() : "<unknown error>");
+ }
- caused_stop = m_gdb_comm.GetInterruptWasSent ();
- }
+ if (!error.Success())
return error;
-}
-Error
-ProcessGDBRemote::DoDetach(bool keep_stopped)
-{
- Error error;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::DoDetach(keep_stopped: %i)", keep_stopped);
+ // Sleep for one second to let the process get all detached...
+ StopAsyncThread();
- error = m_gdb_comm.Detach (keep_stopped);
- if (log)
- {
- if (error.Success())
- log->PutCString ("ProcessGDBRemote::DoDetach() detach packet sent successfully");
- else
- log->Printf ("ProcessGDBRemote::DoDetach() detach packet send failed: %s", error.AsCString() ? error.AsCString() : "<unknown error>");
- }
-
- if (!error.Success())
- return error;
+ SetPrivateState(eStateDetached);
+ ResumePrivateStateThread();
- // Sleep for one second to let the process get all detached...
- StopAsyncThread ();
-
- SetPrivateState (eStateDetached);
- ResumePrivateStateThread();
-
- //KillDebugserverProcess ();
- return error;
+ // KillDebugserverProcess ();
+ return error;
}
-
-Error
-ProcessGDBRemote::DoDestroy ()
-{
- Error error;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy()");
+Error ProcessGDBRemote::DoDestroy() {
+ Error error;
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDestroy()");
#if 0 // XXX Currently no iOS target support on FreeBSD
- // There is a bug in older iOS debugservers where they don't shut down the process
- // they are debugging properly. If the process is sitting at a breakpoint or an exception,
- // this can cause problems with restarting. So we check to see if any of our threads are stopped
- // at a breakpoint, and if so we remove all the breakpoints, resume the process, and THEN
- // destroy it again.
- //
- // Note, we don't have a good way to test the version of debugserver, but I happen to know that
- // the set of all the iOS debugservers which don't support GetThreadSuffixSupported() and that of
- // the debugservers with this bug are equal. There really should be a better way to test this!
- //
- // We also use m_destroy_tried_resuming to make sure we only do this once, if we resume and then halt and
- // get called here to destroy again and we're still at a breakpoint or exception, then we should
- // just do the straight-forward kill.
- //
- // And of course, if we weren't able to stop the process by the time we get here, it isn't
- // necessary (or helpful) to do any of this.
-
- if (!m_gdb_comm.GetThreadSuffixSupported() && m_public_state.GetValue() != eStateRunning)
- {
- PlatformSP platform_sp = GetTarget().GetPlatform();
+ // There is a bug in older iOS debugservers where they don't shut down the
+ // process
+ // they are debugging properly. If the process is sitting at a breakpoint or
+ // an exception,
+ // this can cause problems with restarting. So we check to see if any of our
+ // threads are stopped
+ // at a breakpoint, and if so we remove all the breakpoints, resume the
+ // process, and THEN
+ // destroy it again.
+ //
+ // Note, we don't have a good way to test the version of debugserver, but I
+ // happen to know that
+ // the set of all the iOS debugservers which don't support
+ // GetThreadSuffixSupported() and that of
+ // the debugservers with this bug are equal. There really should be a better
+ // way to test this!
+ //
+ // We also use m_destroy_tried_resuming to make sure we only do this once, if
+ // we resume and then halt and
+ // get called here to destroy again and we're still at a breakpoint or
+ // exception, then we should
+ // just do the straight-forward kill.
+ //
+ // And of course, if we weren't able to stop the process by the time we get
+ // here, it isn't
+ // necessary (or helpful) to do any of this.
+
+ if (!m_gdb_comm.GetThreadSuffixSupported() &&
+ m_public_state.GetValue() != eStateRunning) {
+ PlatformSP platform_sp = GetTarget().GetPlatform();
+
+ // FIXME: These should be ConstStrings so we aren't doing strcmp'ing.
+ if (platform_sp && platform_sp->GetName() &&
+ platform_sp->GetName() == PlatformRemoteiOS::GetPluginNameStatic()) {
+ if (m_destroy_tried_resuming) {
+ if (log)
+ log->PutCString("ProcessGDBRemote::DoDestroy() - Tried resuming to "
+ "destroy once already, not doing it again.");
+ } else {
+ // At present, the plans are discarded and the breakpoints disabled
+ // Process::Destroy,
+ // but we really need it to happen here and it doesn't matter if we do
+ // it twice.
+ m_thread_list.DiscardThreadPlans();
+ DisableAllBreakpointSites();
+
+ bool stop_looks_like_crash = false;
+ ThreadList &threads = GetThreadList();
- // FIXME: These should be ConstStrings so we aren't doing strcmp'ing.
- if (platform_sp
- && platform_sp->GetName()
- && platform_sp->GetName() == PlatformRemoteiOS::GetPluginNameStatic())
{
- if (m_destroy_tried_resuming)
- {
- if (log)
- log->PutCString ("ProcessGDBRemote::DoDestroy() - Tried resuming to destroy once already, not doing it again.");
+ std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+
+ size_t num_threads = threads.GetSize();
+ for (size_t i = 0; i < num_threads; i++) {
+ ThreadSP thread_sp = threads.GetThreadAtIndex(i);
+ StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
+ StopReason reason = eStopReasonInvalid;
+ if (stop_info_sp)
+ reason = stop_info_sp->GetStopReason();
+ if (reason == eStopReasonBreakpoint ||
+ reason == eStopReasonException) {
+ if (log)
+ log->Printf(
+ "ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64
+ " stopped with reason: %s.",
+ thread_sp->GetProtocolID(), stop_info_sp->GetDescription());
+ stop_looks_like_crash = true;
+ break;
}
- else
- {
- // At present, the plans are discarded and the breakpoints disabled Process::Destroy,
- // but we really need it to happen here and it doesn't matter if we do it twice.
- m_thread_list.DiscardThreadPlans();
- DisableAllBreakpointSites();
-
- bool stop_looks_like_crash = false;
- ThreadList &threads = GetThreadList();
-
- {
- std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
-
- size_t num_threads = threads.GetSize();
- for (size_t i = 0; i < num_threads; i++)
- {
- ThreadSP thread_sp = threads.GetThreadAtIndex(i);
- StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
- StopReason reason = eStopReasonInvalid;
- if (stop_info_sp)
- reason = stop_info_sp->GetStopReason();
- if (reason == eStopReasonBreakpoint
- || reason == eStopReasonException)
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy() - thread: 0x%4.4" PRIx64 " stopped with reason: %s.",
- thread_sp->GetProtocolID(),
- stop_info_sp->GetDescription());
- stop_looks_like_crash = true;
- break;
- }
- }
- }
+ }
+ }
- if (stop_looks_like_crash)
- {
- if (log)
- log->PutCString ("ProcessGDBRemote::DoDestroy() - Stopped at a breakpoint, continue and then kill.");
- m_destroy_tried_resuming = true;
-
- // If we are going to run again before killing, it would be good to suspend all the threads
- // before resuming so they won't get into more trouble. Sadly, for the threads stopped with
- // the breakpoint or exception, the exception doesn't get cleared if it is suspended, so we do
- // have to run the risk of letting those threads proceed a bit.
-
- {
- std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
-
- size_t num_threads = threads.GetSize();
- for (size_t i = 0; i < num_threads; i++)
- {
- ThreadSP thread_sp = threads.GetThreadAtIndex(i);
- StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
- StopReason reason = eStopReasonInvalid;
- if (stop_info_sp)
- reason = stop_info_sp->GetStopReason();
- if (reason != eStopReasonBreakpoint
- && reason != eStopReasonException)
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy() - Suspending thread: 0x%4.4" PRIx64 " before running.",
- thread_sp->GetProtocolID());
- thread_sp->SetResumeState(eStateSuspended);
- }
- }
- }
- Resume ();
- return Destroy(false);
- }
+ if (stop_looks_like_crash) {
+ if (log)
+ log->PutCString("ProcessGDBRemote::DoDestroy() - Stopped at a "
+ "breakpoint, continue and then kill.");
+ m_destroy_tried_resuming = true;
+
+ // If we are going to run again before killing, it would be good to
+ // suspend all the threads
+ // before resuming so they won't get into more trouble. Sadly, for
+ // the threads stopped with
+ // the breakpoint or exception, the exception doesn't get cleared if
+ // it is suspended, so we do
+ // have to run the risk of letting those threads proceed a bit.
+
+ {
+ std::lock_guard<std::recursive_mutex> guard(threads.GetMutex());
+
+ size_t num_threads = threads.GetSize();
+ for (size_t i = 0; i < num_threads; i++) {
+ ThreadSP thread_sp = threads.GetThreadAtIndex(i);
+ StopInfoSP stop_info_sp = thread_sp->GetPrivateStopInfo();
+ StopReason reason = eStopReasonInvalid;
+ if (stop_info_sp)
+ reason = stop_info_sp->GetStopReason();
+ if (reason != eStopReasonBreakpoint &&
+ reason != eStopReasonException) {
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDestroy() - Suspending "
+ "thread: 0x%4.4" PRIx64 " before running.",
+ thread_sp->GetProtocolID());
+ thread_sp->SetResumeState(eStateSuspended);
+ }
}
+ }
+ Resume();
+ return Destroy(false);
}
+ }
}
+ }
#endif
- // Interrupt if our inferior is running...
- int exit_status = SIGABRT;
- std::string exit_string;
+ // Interrupt if our inferior is running...
+ int exit_status = SIGABRT;
+ std::string exit_string;
- if (m_gdb_comm.IsConnected())
- {
- if (m_public_state.GetValue() != eStateAttaching)
- {
- StringExtractorGDBRemote response;
- bool send_async = true;
- GDBRemoteCommunication::ScopedTimeout (m_gdb_comm, 3);
+ if (m_gdb_comm.IsConnected()) {
+ if (m_public_state.GetValue() != eStateAttaching) {
+ StringExtractorGDBRemote response;
+ bool send_async = true;
+ GDBRemoteCommunication::ScopedTimeout(m_gdb_comm,
+ std::chrono::seconds(3));
- if (m_gdb_comm.SendPacketAndWaitForResponse("k", 1, response, send_async) == GDBRemoteCommunication::PacketResult::Success)
- {
- char packet_cmd = response.GetChar(0);
+ if (m_gdb_comm.SendPacketAndWaitForResponse("k", response, send_async) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ char packet_cmd = response.GetChar(0);
- if (packet_cmd == 'W' || packet_cmd == 'X')
- {
+ if (packet_cmd == 'W' || packet_cmd == 'X') {
#if defined(__APPLE__)
- // For Native processes on Mac OS X, we launch through the Host Platform, then hand the process off
- // to debugserver, which becomes the parent process through "PT_ATTACH". Then when we go to kill
- // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we call waitpid which returns
- // with no error and the correct status. But amusingly enough that doesn't seem to actually reap
- // the process, but instead it is left around as a Zombie. Probably the kernel is in the process of
- // switching ownership back to lldb which was the original parent, and gets confused in the handoff.
- // Anyway, so call waitpid here to finally reap it.
- PlatformSP platform_sp(GetTarget().GetPlatform());
- if (platform_sp && platform_sp->IsHost())
- {
- int status;
- ::pid_t reap_pid;
- reap_pid = waitpid (GetID(), &status, WNOHANG);
- if (log)
- log->Printf ("Reaped pid: %d, status: %d.\n", reap_pid, status);
- }
-#endif
- SetLastStopPacket (response);
- ClearThreadIDList ();
- exit_status = response.GetHexU8();
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy - got unexpected response to k packet: %s", response.GetStringRef().c_str());
- exit_string.assign("got unexpected response to k packet: ");
- exit_string.append(response.GetStringRef());
- }
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy - failed to send k packet");
- exit_string.assign("failed to send the k packet");
- }
- }
- else
- {
+ // For Native processes on Mac OS X, we launch through the Host
+ // Platform, then hand the process off
+ // to debugserver, which becomes the parent process through
+ // "PT_ATTACH". Then when we go to kill
+ // the process on Mac OS X we call ptrace(PT_KILL) to kill it, then we
+ // call waitpid which returns
+ // with no error and the correct status. But amusingly enough that
+ // doesn't seem to actually reap
+ // the process, but instead it is left around as a Zombie. Probably
+ // the kernel is in the process of
+ // switching ownership back to lldb which was the original parent, and
+ // gets confused in the handoff.
+ // Anyway, so call waitpid here to finally reap it.
+ PlatformSP platform_sp(GetTarget().GetPlatform());
+ if (platform_sp && platform_sp->IsHost()) {
+ int status;
+ ::pid_t reap_pid;
+ reap_pid = waitpid(GetID(), &status, WNOHANG);
if (log)
- log->Printf ("ProcessGDBRemote::DoDestroy - killed or interrupted while attaching");
- exit_string.assign ("killed or interrupted while attaching.");
+ log->Printf("Reaped pid: %d, status: %d.\n", reap_pid, status);
+ }
+#endif
+ SetLastStopPacket(response);
+ ClearThreadIDList();
+ exit_status = response.GetHexU8();
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDestroy - got unexpected response "
+ "to k packet: %s",
+ response.GetStringRef().c_str());
+ exit_string.assign("got unexpected response to k packet: ");
+ exit_string.append(response.GetStringRef());
}
- }
- else
- {
- // If we missed setting the exit status on the way out, do it here.
- // NB set exit status can be called multiple times, the first one sets the status.
- exit_string.assign("destroying when not connected to debugserver");
- }
-
- SetExitStatus(exit_status, exit_string.c_str());
-
- StopAsyncThread ();
- KillDebugserverProcess ();
- return error;
-}
-
-void
-ProcessGDBRemote::SetLastStopPacket (const StringExtractorGDBRemote &response)
-{
- const bool did_exec = response.GetStringRef().find(";reason:exec;") != std::string::npos;
- if (did_exec)
- {
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ } else {
if (log)
- log->Printf ("ProcessGDBRemote::SetLastStopPacket () - detected exec");
+ log->Printf("ProcessGDBRemote::DoDestroy - failed to send k packet");
+ exit_string.assign("failed to send the k packet");
+ }
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemote::DoDestroy - killed or interrupted while "
+ "attaching");
+ exit_string.assign("killed or interrupted while attaching.");
+ }
+ } else {
+ // If we missed setting the exit status on the way out, do it here.
+ // NB set exit status can be called multiple times, the first one sets the
+ // status.
+ exit_string.assign("destroying when not connected to debugserver");
+ }
+
+ SetExitStatus(exit_status, exit_string.c_str());
+
+ StopAsyncThread();
+ KillDebugserverProcess();
+ return error;
+}
- m_thread_list_real.Clear();
- m_thread_list.Clear();
- BuildDynamicRegisterInfo (true);
- m_gdb_comm.ResetDiscoverableSettings (did_exec);
- }
+void ProcessGDBRemote::SetLastStopPacket(
+ const StringExtractorGDBRemote &response) {
+ const bool did_exec =
+ response.GetStringRef().find(";reason:exec;") != std::string::npos;
+ if (did_exec) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::SetLastStopPacket () - detected exec");
- // Scope the lock
- {
- // Lock the thread stack while we access it
- std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
-
- // We are are not using non-stop mode, there can only be one last stop
- // reply packet, so clear the list.
- if (GetTarget().GetNonStopModeEnabled() == false)
- m_stop_packet_stack.clear();
-
- // Add this stop packet to the stop packet stack
- // This stack will get popped and examined when we switch to the
- // Stopped state
- m_stop_packet_stack.push_back(response);
- }
+ m_thread_list_real.Clear();
+ m_thread_list.Clear();
+ BuildDynamicRegisterInfo(true);
+ m_gdb_comm.ResetDiscoverableSettings(did_exec);
+ }
+
+ // Scope the lock
+ {
+ // Lock the thread stack while we access it
+ std::lock_guard<std::recursive_mutex> guard(m_last_stop_packet_mutex);
+
+ // We are are not using non-stop mode, there can only be one last stop
+ // reply packet, so clear the list.
+ if (GetTarget().GetNonStopModeEnabled() == false)
+ m_stop_packet_stack.clear();
+
+ // Add this stop packet to the stop packet stack
+ // This stack will get popped and examined when we switch to the
+ // Stopped state
+ m_stop_packet_stack.push_back(response);
+ }
}
-void
-ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp)
-{
- Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp));
+void ProcessGDBRemote::SetUnixSignals(const UnixSignalsSP &signals_sp) {
+ Process::SetUnixSignals(std::make_shared<GDBRemoteSignals>(signals_sp));
}
//------------------------------------------------------------------
// Process Queries
//------------------------------------------------------------------
-bool
-ProcessGDBRemote::IsAlive ()
-{
- return m_gdb_comm.IsConnected() && Process::IsAlive();
+bool ProcessGDBRemote::IsAlive() {
+ return m_gdb_comm.IsConnected() && Process::IsAlive();
}
-addr_t
-ProcessGDBRemote::GetImageInfoAddress()
-{
- // request the link map address via the $qShlibInfoAddr packet
- lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr();
+addr_t ProcessGDBRemote::GetImageInfoAddress() {
+ // request the link map address via the $qShlibInfoAddr packet
+ lldb::addr_t addr = m_gdb_comm.GetShlibInfoAddr();
- // the loaded module list can also provides a link map address
- if (addr == LLDB_INVALID_ADDRESS)
- {
- LoadedModuleInfoList list;
- if (GetLoadedModuleList (list).Success())
- addr = list.m_link_map;
- }
+ // the loaded module list can also provides a link map address
+ if (addr == LLDB_INVALID_ADDRESS) {
+ LoadedModuleInfoList list;
+ if (GetLoadedModuleList(list).Success())
+ addr = list.m_link_map;
+ }
- return addr;
+ return addr;
}
-void
-ProcessGDBRemote::WillPublicStop ()
-{
- // See if the GDB remote client supports the JSON threads info.
- // If so, we gather stop info for all threads, expedited registers,
- // expedited memory, runtime queue information (iOS and MacOSX only),
- // and more. Expediting memory will help stack backtracing be much
- // faster. Expediting registers will make sure we don't have to read
- // the thread registers for GPRs.
- m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();
-
- if (m_jthreadsinfo_sp)
- {
- // Now set the stop info for each thread and also expedite any registers
- // and memory that was in the jThreadsInfo response.
- StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
- if (thread_infos)
- {
- const size_t n = thread_infos->GetSize();
- for (size_t i=0; i<n; ++i)
- {
- StructuredData::Dictionary *thread_dict = thread_infos->GetItemAtIndex(i)->GetAsDictionary();
- if (thread_dict)
- SetThreadStopInfo(thread_dict);
- }
- }
- }
+void ProcessGDBRemote::WillPublicStop() {
+ // See if the GDB remote client supports the JSON threads info.
+ // If so, we gather stop info for all threads, expedited registers,
+ // expedited memory, runtime queue information (iOS and MacOSX only),
+ // and more. Expediting memory will help stack backtracing be much
+ // faster. Expediting registers will make sure we don't have to read
+ // the thread registers for GPRs.
+ m_jthreadsinfo_sp = m_gdb_comm.GetThreadsInfo();
+
+ if (m_jthreadsinfo_sp) {
+ // Now set the stop info for each thread and also expedite any registers
+ // and memory that was in the jThreadsInfo response.
+ StructuredData::Array *thread_infos = m_jthreadsinfo_sp->GetAsArray();
+ if (thread_infos) {
+ const size_t n = thread_infos->GetSize();
+ for (size_t i = 0; i < n; ++i) {
+ StructuredData::Dictionary *thread_dict =
+ thread_infos->GetItemAtIndex(i)->GetAsDictionary();
+ if (thread_dict)
+ SetThreadStopInfo(thread_dict);
+ }
+ }
+ }
}
//------------------------------------------------------------------
// Process Memory
//------------------------------------------------------------------
-size_t
-ProcessGDBRemote::DoReadMemory (addr_t addr, void *buf, size_t size, Error &error)
-{
- GetMaxMemorySize ();
- if (size > m_max_memory_size)
- {
- // Keep memory read sizes down to a sane limit. This function will be
- // called multiple times in order to complete the task by
- // lldb_private::Process so it is ok to do this.
- size = m_max_memory_size;
- }
-
- char packet[64];
- int packet_len;
- bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
- packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64,
- binary_memory_read ? 'x' : 'm', (uint64_t)addr, (uint64_t)size);
- assert (packet_len + 1 < (int)sizeof(packet));
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet, packet_len, response, true) == GDBRemoteCommunication::PacketResult::Success)
- {
- if (response.IsNormalResponse())
- {
- error.Clear();
- if (binary_memory_read)
- {
- // The lower level GDBRemoteCommunication packet receive layer has already de-quoted any
- // 0x7d character escaping that was present in the packet
-
- size_t data_received_size = response.GetBytesLeft();
- if (data_received_size > size)
- {
- // Don't write past the end of BUF if the remote debug server gave us too
- // much data for some reason.
- data_received_size = size;
- }
- memcpy (buf, response.GetStringRef().data(), data_received_size);
- return data_received_size;
- }
- else
- {
- return response.GetHexBytes(buf, size, '\xdd');
- }
+size_t ProcessGDBRemote::DoReadMemory(addr_t addr, void *buf, size_t size,
+ Error &error) {
+ GetMaxMemorySize();
+ if (size > m_max_memory_size) {
+ // Keep memory read sizes down to a sane limit. This function will be
+ // called multiple times in order to complete the task by
+ // lldb_private::Process so it is ok to do this.
+ size = m_max_memory_size;
+ }
+
+ char packet[64];
+ int packet_len;
+ bool binary_memory_read = m_gdb_comm.GetxPacketSupported();
+ packet_len = ::snprintf(packet, sizeof(packet), "%c%" PRIx64 ",%" PRIx64,
+ binary_memory_read ? 'x' : 'm', (uint64_t)addr,
+ (uint64_t)size);
+ assert(packet_len + 1 < (int)sizeof(packet));
+ UNUSED_IF_ASSERT_DISABLED(packet_len);
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet, response, true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsNormalResponse()) {
+ error.Clear();
+ if (binary_memory_read) {
+ // The lower level GDBRemoteCommunication packet receive layer has
+ // already de-quoted any
+ // 0x7d character escaping that was present in the packet
+
+ size_t data_received_size = response.GetBytesLeft();
+ if (data_received_size > size) {
+ // Don't write past the end of BUF if the remote debug server gave us
+ // too
+ // much data for some reason.
+ data_received_size = size;
}
- else if (response.IsErrorResponse())
- error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr);
- else if (response.IsUnsupportedResponse())
- error.SetErrorStringWithFormat("GDB server does not support reading memory");
- else
- error.SetErrorStringWithFormat("unexpected response to GDB server memory read packet '%s': '%s'", packet, response.GetStringRef().c_str());
- }
+ memcpy(buf, response.GetStringRef().data(), data_received_size);
+ return data_received_size;
+ } else {
+ return response.GetHexBytes(
+ llvm::MutableArrayRef<uint8_t>((uint8_t *)buf, size), '\xdd');
+ }
+ } else if (response.IsErrorResponse())
+ error.SetErrorStringWithFormat("memory read failed for 0x%" PRIx64, addr);
+ else if (response.IsUnsupportedResponse())
+ error.SetErrorStringWithFormat(
+ "GDB server does not support reading memory");
else
- {
- error.SetErrorStringWithFormat("failed to send packet: '%s'", packet);
- }
- return 0;
+ error.SetErrorStringWithFormat(
+ "unexpected response to GDB server memory read packet '%s': '%s'",
+ packet, response.GetStringRef().c_str());
+ } else {
+ error.SetErrorStringWithFormat("failed to send packet: '%s'", packet);
+ }
+ return 0;
}
-size_t
-ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Error &error)
-{
- GetMaxMemorySize ();
- if (size > m_max_memory_size)
- {
- // Keep memory read sizes down to a sane limit. This function will be
- // called multiple times in order to complete the task by
- // lldb_private::Process so it is ok to do this.
- size = m_max_memory_size;
- }
-
- StreamString packet;
- packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
- packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(), endian::InlHostByteOrder());
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, true) == GDBRemoteCommunication::PacketResult::Success)
- {
- if (response.IsOKResponse())
- {
- error.Clear();
- return size;
- }
- else if (response.IsErrorResponse())
- error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64, addr);
- else if (response.IsUnsupportedResponse())
- error.SetErrorStringWithFormat("GDB server does not support writing memory");
- else
- error.SetErrorStringWithFormat("unexpected response to GDB server memory write packet '%s': '%s'", packet.GetString().c_str(), response.GetStringRef().c_str());
- }
+size_t ProcessGDBRemote::DoWriteMemory(addr_t addr, const void *buf,
+ size_t size, Error &error) {
+ GetMaxMemorySize();
+ if (size > m_max_memory_size) {
+ // Keep memory read sizes down to a sane limit. This function will be
+ // called multiple times in order to complete the task by
+ // lldb_private::Process so it is ok to do this.
+ size = m_max_memory_size;
+ }
+
+ StreamString packet;
+ packet.Printf("M%" PRIx64 ",%" PRIx64 ":", addr, (uint64_t)size);
+ packet.PutBytesAsRawHex8(buf, size, endian::InlHostByteOrder(),
+ endian::InlHostByteOrder());
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
+ true) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ if (response.IsOKResponse()) {
+ error.Clear();
+ return size;
+ } else if (response.IsErrorResponse())
+ error.SetErrorStringWithFormat("memory write failed for 0x%" PRIx64,
+ addr);
+ else if (response.IsUnsupportedResponse())
+ error.SetErrorStringWithFormat(
+ "GDB server does not support writing memory");
else
- {
- error.SetErrorStringWithFormat("failed to send packet: '%s'", packet.GetString().c_str());
- }
- return 0;
+ error.SetErrorStringWithFormat(
+ "unexpected response to GDB server memory write packet '%s': '%s'",
+ packet.GetData(), response.GetStringRef().c_str());
+ } else {
+ error.SetErrorStringWithFormat("failed to send packet: '%s'",
+ packet.GetData());
+ }
+ return 0;
}
-lldb::addr_t
-ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
-{
- Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_EXPRESSIONS));
- addr_t allocated_addr = LLDB_INVALID_ADDRESS;
-
- if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo)
- {
- allocated_addr = m_gdb_comm.AllocateMemory (size, permissions);
- if (allocated_addr != LLDB_INVALID_ADDRESS || m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes)
- return allocated_addr;
- }
-
- if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo)
- {
- // Call mmap() to create memory in the inferior..
- unsigned prot = 0;
- if (permissions & lldb::ePermissionsReadable)
- prot |= eMmapProtRead;
- if (permissions & lldb::ePermissionsWritable)
- prot |= eMmapProtWrite;
- if (permissions & lldb::ePermissionsExecutable)
- prot |= eMmapProtExec;
-
- if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
- eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0))
- m_addr_to_mmap_size[allocated_addr] = size;
- else
- {
- allocated_addr = LLDB_INVALID_ADDRESS;
- if (log)
- log->Printf ("ProcessGDBRemote::%s no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?", __FUNCTION__);
- }
- }
-
- if (allocated_addr == LLDB_INVALID_ADDRESS)
- error.SetErrorStringWithFormat("unable to allocate %" PRIu64 " bytes of memory with permissions %s", (uint64_t)size, GetPermissionsAsCString (permissions));
- else
- error.Clear();
- return allocated_addr;
+lldb::addr_t ProcessGDBRemote::DoAllocateMemory(size_t size,
+ uint32_t permissions,
+ Error &error) {
+ Log *log(
+ GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_EXPRESSIONS));
+ addr_t allocated_addr = LLDB_INVALID_ADDRESS;
+
+ if (m_gdb_comm.SupportsAllocDeallocMemory() != eLazyBoolNo) {
+ allocated_addr = m_gdb_comm.AllocateMemory(size, permissions);
+ if (allocated_addr != LLDB_INVALID_ADDRESS ||
+ m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolYes)
+ return allocated_addr;
+ }
+
+ if (m_gdb_comm.SupportsAllocDeallocMemory() == eLazyBoolNo) {
+ // Call mmap() to create memory in the inferior..
+ unsigned prot = 0;
+ if (permissions & lldb::ePermissionsReadable)
+ prot |= eMmapProtRead;
+ if (permissions & lldb::ePermissionsWritable)
+ prot |= eMmapProtWrite;
+ if (permissions & lldb::ePermissionsExecutable)
+ prot |= eMmapProtExec;
+
+ if (InferiorCallMmap(this, allocated_addr, 0, size, prot,
+ eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0))
+ m_addr_to_mmap_size[allocated_addr] = size;
+ else {
+ allocated_addr = LLDB_INVALID_ADDRESS;
+ if (log)
+ log->Printf("ProcessGDBRemote::%s no direct stub support for memory "
+ "allocation, and InferiorCallMmap also failed - is stub "
+ "missing register context save/restore capability?",
+ __FUNCTION__);
+ }
+ }
+
+ if (allocated_addr == LLDB_INVALID_ADDRESS)
+ error.SetErrorStringWithFormat(
+ "unable to allocate %" PRIu64 " bytes of memory with permissions %s",
+ (uint64_t)size, GetPermissionsAsCString(permissions));
+ else
+ error.Clear();
+ return allocated_addr;
}
-Error
-ProcessGDBRemote::GetMemoryRegionInfo (addr_t load_addr,
- MemoryRegionInfo &region_info)
-{
+Error ProcessGDBRemote::GetMemoryRegionInfo(addr_t load_addr,
+ MemoryRegionInfo &region_info) {
- Error error (m_gdb_comm.GetMemoryRegionInfo (load_addr, region_info));
- return error;
+ Error error(m_gdb_comm.GetMemoryRegionInfo(load_addr, region_info));
+ return error;
}
-Error
-ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num)
-{
+Error ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num) {
- Error error (m_gdb_comm.GetWatchpointSupportInfo (num));
- return error;
+ Error error(m_gdb_comm.GetWatchpointSupportInfo(num));
+ return error;
}
-Error
-ProcessGDBRemote::GetWatchpointSupportInfo (uint32_t &num, bool& after)
-{
- Error error (m_gdb_comm.GetWatchpointSupportInfo (num, after, GetTarget().GetArchitecture()));
- return error;
+Error ProcessGDBRemote::GetWatchpointSupportInfo(uint32_t &num, bool &after) {
+ Error error(m_gdb_comm.GetWatchpointSupportInfo(
+ num, after, GetTarget().GetArchitecture()));
+ return error;
}
-Error
-ProcessGDBRemote::DoDeallocateMemory (lldb::addr_t addr)
-{
- Error error;
- LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();
-
- switch (supported)
- {
- case eLazyBoolCalculate:
- // We should never be deallocating memory without allocating memory
- // first so we should never get eLazyBoolCalculate
- error.SetErrorString ("tried to deallocate memory without ever allocating memory");
- break;
-
- case eLazyBoolYes:
- if (!m_gdb_comm.DeallocateMemory (addr))
- error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
- break;
-
- case eLazyBoolNo:
- // Call munmap() to deallocate memory in the inferior..
- {
- MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
- if (pos != m_addr_to_mmap_size.end() &&
- InferiorCallMunmap(this, addr, pos->second))
- m_addr_to_mmap_size.erase (pos);
- else
- error.SetErrorStringWithFormat("unable to deallocate memory at 0x%" PRIx64, addr);
- }
- break;
- }
-
- return error;
+Error ProcessGDBRemote::DoDeallocateMemory(lldb::addr_t addr) {
+ Error error;
+ LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();
+
+ switch (supported) {
+ case eLazyBoolCalculate:
+ // We should never be deallocating memory without allocating memory
+ // first so we should never get eLazyBoolCalculate
+ error.SetErrorString(
+ "tried to deallocate memory without ever allocating memory");
+ break;
+
+ case eLazyBoolYes:
+ if (!m_gdb_comm.DeallocateMemory(addr))
+ error.SetErrorStringWithFormat(
+ "unable to deallocate memory at 0x%" PRIx64, addr);
+ break;
+
+ case eLazyBoolNo:
+ // Call munmap() to deallocate memory in the inferior..
+ {
+ MMapMap::iterator pos = m_addr_to_mmap_size.find(addr);
+ if (pos != m_addr_to_mmap_size.end() &&
+ InferiorCallMunmap(this, addr, pos->second))
+ m_addr_to_mmap_size.erase(pos);
+ else
+ error.SetErrorStringWithFormat(
+ "unable to deallocate memory at 0x%" PRIx64, addr);
+ }
+ break;
+ }
+
+ return error;
}
-
//------------------------------------------------------------------
// Process STDIO
//------------------------------------------------------------------
-size_t
-ProcessGDBRemote::PutSTDIN (const char *src, size_t src_len, Error &error)
-{
- if (m_stdio_communication.IsConnected())
- {
- ConnectionStatus status;
- m_stdio_communication.Write(src, src_len, status, NULL);
- }
- else if (m_stdin_forward)
- {
- m_gdb_comm.SendStdinNotification(src, src_len);
- }
- return 0;
+size_t ProcessGDBRemote::PutSTDIN(const char *src, size_t src_len,
+ Error &error) {
+ if (m_stdio_communication.IsConnected()) {
+ ConnectionStatus status;
+ m_stdio_communication.Write(src, src_len, status, NULL);
+ } else if (m_stdin_forward) {
+ m_gdb_comm.SendStdinNotification(src, src_len);
+ }
+ return 0;
}
-Error
-ProcessGDBRemote::EnableBreakpointSite (BreakpointSite *bp_site)
-{
- Error error;
- assert(bp_site != NULL);
-
- // Get logging info
- Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
- user_id_t site_id = bp_site->GetID();
-
- // Get the breakpoint address
- const addr_t addr = bp_site->GetLoadAddress();
-
- // Log that a breakpoint was requested
- if (log)
- log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64, site_id, (uint64_t)addr);
-
- // Breakpoint already exists and is enabled
- if (bp_site->IsEnabled())
- {
- if (log)
- log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64 ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)", site_id, (uint64_t)addr);
- return error;
- }
+Error ProcessGDBRemote::EnableBreakpointSite(BreakpointSite *bp_site) {
+ Error error;
+ assert(bp_site != NULL);
- // Get the software breakpoint trap opcode size
- const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);
+ // Get logging info
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
+ user_id_t site_id = bp_site->GetID();
- // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this breakpoint type
- // is supported by the remote stub. These are set to true by default, and later set to false
- // only after we receive an unimplemented response when sending a breakpoint packet. This means
- // initially that unless we were specifically instructed to use a hardware breakpoint, LLDB will
- // attempt to set a software breakpoint. HardwareRequired() also queries a boolean variable which
- // indicates if the user specifically asked for hardware breakpoints. If true then we will
- // skip over software breakpoints.
- if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) && (!bp_site->HardwareRequired()))
- {
- // Try to send off a software breakpoint packet ($Z0)
- uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointSoftware, true, addr, bp_op_size);
- if (error_no == 0)
- {
- // The breakpoint was placed successfully
- bp_site->SetEnabled(true);
- bp_site->SetType(BreakpointSite::eExternal);
- return error;
- }
+ // Get the breakpoint address
+ const addr_t addr = bp_site->GetLoadAddress();
- // SendGDBStoppointTypePacket() will return an error if it was unable to set this
- // breakpoint. We need to differentiate between a error specific to placing this breakpoint
- // or if we have learned that this breakpoint type is unsupported. To do this, we
- // must test the support boolean for this breakpoint type to see if it now indicates that
- // this breakpoint type is unsupported. If they are still supported then we should return
- // with the error code. If they are now unsupported, then we would like to fall through
- // and try another form of breakpoint.
- if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware))
- {
- if (error_no != UINT8_MAX)
- error.SetErrorStringWithFormat("error: %d sending the breakpoint request", errno);
- else
- error.SetErrorString("error sending the breakpoint request");
- return error;
- }
-
- // We reach here when software breakpoints have been found to be unsupported. For future
- // calls to set a breakpoint, we will not attempt to set a breakpoint with a type that is
- // known not to be supported.
- if (log)
- log->Printf("Software breakpoints are unsupported");
-
- // So we will fall through and try a hardware breakpoint
- }
-
- // The process of setting a hardware breakpoint is much the same as above. We check the
- // supported boolean for this breakpoint type, and if it is thought to be supported then we
- // will try to set this breakpoint with a hardware breakpoint.
- if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware))
- {
- // Try to send off a hardware breakpoint packet ($Z1)
- uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, true, addr, bp_op_size);
- if (error_no == 0)
- {
- // The breakpoint was placed successfully
- bp_site->SetEnabled(true);
- bp_site->SetType(BreakpointSite::eHardware);
- return error;
- }
-
- // Check if the error was something other then an unsupported breakpoint type
- if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware))
- {
- // Unable to set this hardware breakpoint
- if (error_no != UINT8_MAX)
- error.SetErrorStringWithFormat("error: %d sending the hardware breakpoint request "
- "(hardware breakpoint resources might be exhausted or unavailable)",
- error_no);
- else
- error.SetErrorString("error sending the hardware breakpoint request (hardware breakpoint resources "
- "might be exhausted or unavailable)");
- return error;
- }
+ // Log that a breakpoint was requested
+ if (log)
+ log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64
+ ") address = 0x%" PRIx64,
+ site_id, (uint64_t)addr);
- // We will reach here when the stub gives an unsupported response to a hardware breakpoint
- if (log)
- log->Printf("Hardware breakpoints are unsupported");
+ // Breakpoint already exists and is enabled
+ if (bp_site->IsEnabled()) {
+ if (log)
+ log->Printf("ProcessGDBRemote::EnableBreakpointSite (size_id = %" PRIu64
+ ") address = 0x%" PRIx64 " -- SUCCESS (already enabled)",
+ site_id, (uint64_t)addr);
+ return error;
+ }
+
+ // Get the software breakpoint trap opcode size
+ const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);
+
+ // SupportsGDBStoppointPacket() simply checks a boolean, indicating if this
+ // breakpoint type
+ // is supported by the remote stub. These are set to true by default, and
+ // later set to false
+ // only after we receive an unimplemented response when sending a breakpoint
+ // packet. This means
+ // initially that unless we were specifically instructed to use a hardware
+ // breakpoint, LLDB will
+ // attempt to set a software breakpoint. HardwareRequired() also queries a
+ // boolean variable which
+ // indicates if the user specifically asked for hardware breakpoints. If true
+ // then we will
+ // skip over software breakpoints.
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware) &&
+ (!bp_site->HardwareRequired())) {
+ // Try to send off a software breakpoint packet ($Z0)
+ uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
+ eBreakpointSoftware, true, addr, bp_op_size);
+ if (error_no == 0) {
+ // The breakpoint was placed successfully
+ bp_site->SetEnabled(true);
+ bp_site->SetType(BreakpointSite::eExternal);
+ return error;
+ }
+
+ // SendGDBStoppointTypePacket() will return an error if it was unable to set
+ // this
+ // breakpoint. We need to differentiate between a error specific to placing
+ // this breakpoint
+ // or if we have learned that this breakpoint type is unsupported. To do
+ // this, we
+ // must test the support boolean for this breakpoint type to see if it now
+ // indicates that
+ // this breakpoint type is unsupported. If they are still supported then we
+ // should return
+ // with the error code. If they are now unsupported, then we would like to
+ // fall through
+ // and try another form of breakpoint.
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointSoftware)) {
+ if (error_no != UINT8_MAX)
+ error.SetErrorStringWithFormat(
+ "error: %d sending the breakpoint request", errno);
+ else
+ error.SetErrorString("error sending the breakpoint request");
+ return error;
+ }
+
+ // We reach here when software breakpoints have been found to be
+ // unsupported. For future
+ // calls to set a breakpoint, we will not attempt to set a breakpoint with a
+ // type that is
+ // known not to be supported.
+ if (log)
+ log->Printf("Software breakpoints are unsupported");
+
+ // So we will fall through and try a hardware breakpoint
+ }
+
+ // The process of setting a hardware breakpoint is much the same as above. We
+ // check the
+ // supported boolean for this breakpoint type, and if it is thought to be
+ // supported then we
+ // will try to set this breakpoint with a hardware breakpoint.
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
+ // Try to send off a hardware breakpoint packet ($Z1)
+ uint8_t error_no = m_gdb_comm.SendGDBStoppointTypePacket(
+ eBreakpointHardware, true, addr, bp_op_size);
+ if (error_no == 0) {
+ // The breakpoint was placed successfully
+ bp_site->SetEnabled(true);
+ bp_site->SetType(BreakpointSite::eHardware);
+ return error;
+ }
+
+ // Check if the error was something other then an unsupported breakpoint
+ // type
+ if (m_gdb_comm.SupportsGDBStoppointPacket(eBreakpointHardware)) {
+ // Unable to set this hardware breakpoint
+ if (error_no != UINT8_MAX)
+ error.SetErrorStringWithFormat(
+ "error: %d sending the hardware breakpoint request "
+ "(hardware breakpoint resources might be exhausted or unavailable)",
+ error_no);
+ else
+ error.SetErrorString("error sending the hardware breakpoint request "
+ "(hardware breakpoint resources "
+ "might be exhausted or unavailable)");
+ return error;
+ }
+
+ // We will reach here when the stub gives an unsupported response to a
+ // hardware breakpoint
+ if (log)
+ log->Printf("Hardware breakpoints are unsupported");
- // Finally we will falling through to a #trap style breakpoint
- }
+ // Finally we will falling through to a #trap style breakpoint
+ }
- // Don't fall through when hardware breakpoints were specifically requested
- if (bp_site->HardwareRequired())
- {
- error.SetErrorString("hardware breakpoints are not supported");
- return error;
- }
+ // Don't fall through when hardware breakpoints were specifically requested
+ if (bp_site->HardwareRequired()) {
+ error.SetErrorString("hardware breakpoints are not supported");
+ return error;
+ }
- // As a last resort we want to place a manual breakpoint. An instruction
- // is placed into the process memory using memory write packets.
- return EnableSoftwareBreakpoint(bp_site);
+ // As a last resort we want to place a manual breakpoint. An instruction
+ // is placed into the process memory using memory write packets.
+ return EnableSoftwareBreakpoint(bp_site);
}
-Error
-ProcessGDBRemote::DisableBreakpointSite (BreakpointSite *bp_site)
-{
- Error error;
- assert (bp_site != NULL);
- addr_t addr = bp_site->GetLoadAddress();
- user_id_t site_id = bp_site->GetID();
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
- if (log)
- log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64, site_id, (uint64_t)addr);
-
- if (bp_site->IsEnabled())
- {
- const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode (bp_site);
+Error ProcessGDBRemote::DisableBreakpointSite(BreakpointSite *bp_site) {
+ Error error;
+ assert(bp_site != NULL);
+ addr_t addr = bp_site->GetLoadAddress();
+ user_id_t site_id = bp_site->GetID();
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_BREAKPOINTS));
+ if (log)
+ log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64
+ ") addr = 0x%8.8" PRIx64,
+ site_id, (uint64_t)addr);
+
+ if (bp_site->IsEnabled()) {
+ const size_t bp_op_size = GetSoftwareBreakpointTrapOpcode(bp_site);
- BreakpointSite::Type bp_type = bp_site->GetType();
- switch (bp_type)
- {
- case BreakpointSite::eSoftware:
- error = DisableSoftwareBreakpoint (bp_site);
- break;
+ BreakpointSite::Type bp_type = bp_site->GetType();
+ switch (bp_type) {
+ case BreakpointSite::eSoftware:
+ error = DisableSoftwareBreakpoint(bp_site);
+ break;
- case BreakpointSite::eHardware:
- if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false, addr, bp_op_size))
- error.SetErrorToGenericError();
- break;
+ case BreakpointSite::eHardware:
+ if (m_gdb_comm.SendGDBStoppointTypePacket(eBreakpointHardware, false,
+ addr, bp_op_size))
+ error.SetErrorToGenericError();
+ break;
- case BreakpointSite::eExternal:
- {
- GDBStoppointType stoppoint_type;
- if (bp_site->IsHardware())
- stoppoint_type = eBreakpointHardware;
- else
- stoppoint_type = eBreakpointSoftware;
+ case BreakpointSite::eExternal: {
+ GDBStoppointType stoppoint_type;
+ if (bp_site->IsHardware())
+ stoppoint_type = eBreakpointHardware;
+ else
+ stoppoint_type = eBreakpointSoftware;
- if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr, bp_op_size))
- error.SetErrorToGenericError();
- }
- break;
- }
- if (error.Success())
- bp_site->SetEnabled(false);
- }
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", site_id, (uint64_t)addr);
- return error;
+ if (m_gdb_comm.SendGDBStoppointTypePacket(stoppoint_type, false, addr,
+ bp_op_size))
+ error.SetErrorToGenericError();
+ } break;
}
-
if (error.Success())
- error.SetErrorToGenericError();
+ bp_site->SetEnabled(false);
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemote::DisableBreakpointSite (site_id = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)",
+ site_id, (uint64_t)addr);
return error;
+ }
+
+ if (error.Success())
+ error.SetErrorToGenericError();
+ return error;
}
// Pre-requisite: wp != NULL.
-static GDBStoppointType
-GetGDBStoppointType (Watchpoint *wp)
-{
- assert(wp);
- bool watch_read = wp->WatchpointRead();
- bool watch_write = wp->WatchpointWrite();
-
- // watch_read and watch_write cannot both be false.
- assert(watch_read || watch_write);
- if (watch_read && watch_write)
- return eWatchpointReadWrite;
- else if (watch_read)
- return eWatchpointRead;
- else // Must be watch_write, then.
- return eWatchpointWrite;
+static GDBStoppointType GetGDBStoppointType(Watchpoint *wp) {
+ assert(wp);
+ bool watch_read = wp->WatchpointRead();
+ bool watch_write = wp->WatchpointWrite();
+
+ // watch_read and watch_write cannot both be false.
+ assert(watch_read || watch_write);
+ if (watch_read && watch_write)
+ return eWatchpointReadWrite;
+ else if (watch_read)
+ return eWatchpointRead;
+ else // Must be watch_write, then.
+ return eWatchpointWrite;
}
-Error
-ProcessGDBRemote::EnableWatchpoint (Watchpoint *wp, bool notify)
-{
- Error error;
- if (wp)
- {
- user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")", watchID);
- if (wp->IsEnabled())
- {
- if (log)
- log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.", watchID, (uint64_t)addr);
- return error;
- }
-
- GDBStoppointType type = GetGDBStoppointType(wp);
- // Pass down an appropriate z/Z packet...
- if (m_gdb_comm.SupportsGDBStoppointPacket (type))
- {
- if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr, wp->GetByteSize()) == 0)
- {
- wp->SetEnabled(true, notify);
- return error;
- }
- else
- error.SetErrorString("sending gdb watchpoint packet failed");
- }
- else
- error.SetErrorString("watchpoints not supported");
- }
- else
- {
- error.SetErrorString("Watchpoint argument was NULL.");
- }
- if (error.Success())
- error.SetErrorToGenericError();
- return error;
+Error ProcessGDBRemote::EnableWatchpoint(Watchpoint *wp, bool notify) {
+ Error error;
+ if (wp) {
+ user_id_t watchID = wp->GetID();
+ addr_t addr = wp->GetLoadAddress();
+ Log *log(
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
+ if (log)
+ log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64 ")",
+ watchID);
+ if (wp->IsEnabled()) {
+ if (log)
+ log->Printf("ProcessGDBRemote::EnableWatchpoint(watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 ": watchpoint already enabled.",
+ watchID, (uint64_t)addr);
+ return error;
+ }
+
+ GDBStoppointType type = GetGDBStoppointType(wp);
+ // Pass down an appropriate z/Z packet...
+ if (m_gdb_comm.SupportsGDBStoppointPacket(type)) {
+ if (m_gdb_comm.SendGDBStoppointTypePacket(type, true, addr,
+ wp->GetByteSize()) == 0) {
+ wp->SetEnabled(true, notify);
+ return error;
+ } else
+ error.SetErrorString("sending gdb watchpoint packet failed");
+ } else
+ error.SetErrorString("watchpoints not supported");
+ } else {
+ error.SetErrorString("Watchpoint argument was NULL.");
+ }
+ if (error.Success())
+ error.SetErrorToGenericError();
+ return error;
}
-Error
-ProcessGDBRemote::DisableWatchpoint (Watchpoint *wp, bool notify)
-{
- Error error;
- if (wp)
- {
- user_id_t watchID = wp->GetID();
-
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
+Error ProcessGDBRemote::DisableWatchpoint(Watchpoint *wp, bool notify) {
+ Error error;
+ if (wp) {
+ user_id_t watchID = wp->GetID();
- addr_t addr = wp->GetLoadAddress();
+ Log *log(
+ ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_WATCHPOINTS));
- if (log)
- log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64, watchID, (uint64_t)addr);
-
- if (!wp->IsEnabled())
- {
- if (log)
- log->Printf ("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64 ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)", watchID, (uint64_t)addr);
- // See also 'class WatchpointSentry' within StopInfo.cpp.
- // This disabling attempt might come from the user-supplied actions, we'll route it in order for
- // the watchpoint object to intelligently process this action.
- wp->SetEnabled(false, notify);
- return error;
- }
+ addr_t addr = wp->GetLoadAddress();
- if (wp->IsHardware())
- {
- GDBStoppointType type = GetGDBStoppointType(wp);
- // Pass down an appropriate z/Z packet...
- if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr, wp->GetByteSize()) == 0)
- {
- wp->SetEnabled(false, notify);
- return error;
- }
- else
- error.SetErrorString("sending gdb watchpoint packet failed");
- }
- // TODO: clear software watchpoints if we implement them
- }
- else
- {
- error.SetErrorString("Watchpoint argument was NULL.");
- }
- if (error.Success())
- error.SetErrorToGenericError();
- return error;
+ if (log)
+ log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64,
+ watchID, (uint64_t)addr);
+
+ if (!wp->IsEnabled()) {
+ if (log)
+ log->Printf("ProcessGDBRemote::DisableWatchpoint (watchID = %" PRIu64
+ ") addr = 0x%8.8" PRIx64 " -- SUCCESS (already disabled)",
+ watchID, (uint64_t)addr);
+ // See also 'class WatchpointSentry' within StopInfo.cpp.
+ // This disabling attempt might come from the user-supplied actions, we'll
+ // route it in order for
+ // the watchpoint object to intelligently process this action.
+ wp->SetEnabled(false, notify);
+ return error;
+ }
+
+ if (wp->IsHardware()) {
+ GDBStoppointType type = GetGDBStoppointType(wp);
+ // Pass down an appropriate z/Z packet...
+ if (m_gdb_comm.SendGDBStoppointTypePacket(type, false, addr,
+ wp->GetByteSize()) == 0) {
+ wp->SetEnabled(false, notify);
+ return error;
+ } else
+ error.SetErrorString("sending gdb watchpoint packet failed");
+ }
+ // TODO: clear software watchpoints if we implement them
+ } else {
+ error.SetErrorString("Watchpoint argument was NULL.");
+ }
+ if (error.Success())
+ error.SetErrorToGenericError();
+ return error;
}
-void
-ProcessGDBRemote::Clear()
-{
- m_flags = 0;
- m_thread_list_real.Clear();
- m_thread_list.Clear();
+void ProcessGDBRemote::Clear() {
+ m_flags = 0;
+ m_thread_list_real.Clear();
+ m_thread_list.Clear();
}
-Error
-ProcessGDBRemote::DoSignal (int signo)
-{
- Error error;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::DoSignal (signal = %d)", signo);
+Error ProcessGDBRemote::DoSignal(int signo) {
+ Error error;
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::DoSignal (signal = %d)", signo);
- if (!m_gdb_comm.SendAsyncSignal (signo))
- error.SetErrorStringWithFormat("failed to send signal %i", signo);
- return error;
+ if (!m_gdb_comm.SendAsyncSignal(signo))
+ error.SetErrorStringWithFormat("failed to send signal %i", signo);
+ return error;
}
-Error
-ProcessGDBRemote::EstablishConnectionIfNeeded (const ProcessInfo &process_info)
-{
- // Make sure we aren't already connected?
- if (m_gdb_comm.IsConnected())
- return Error();
-
- PlatformSP platform_sp (GetTarget ().GetPlatform ());
- if (platform_sp && !platform_sp->IsHost ())
- return Error("Lost debug server connection");
+Error ProcessGDBRemote::EstablishConnectionIfNeeded(
+ const ProcessInfo &process_info) {
+ // Make sure we aren't already connected?
+ if (m_gdb_comm.IsConnected())
+ return Error();
- auto error = LaunchAndConnectToDebugserver (process_info);
- if (error.Fail())
- {
- const char *error_string = error.AsCString();
- if (error_string == nullptr)
- error_string = "unable to launch " DEBUGSERVER_BASENAME;
- }
- return error;
+ PlatformSP platform_sp(GetTarget().GetPlatform());
+ if (platform_sp && !platform_sp->IsHost())
+ return Error("Lost debug server connection");
+
+ auto error = LaunchAndConnectToDebugserver(process_info);
+ if (error.Fail()) {
+ const char *error_string = error.AsCString();
+ if (error_string == nullptr)
+ error_string = "unable to launch " DEBUGSERVER_BASENAME;
+ }
+ return error;
}
+#if defined(__APPLE__)
+#define USE_SOCKETPAIR_FOR_LOCAL_CONNECTION 1
+#endif
-Error
-ProcessGDBRemote::LaunchAndConnectToDebugserver (const ProcessInfo &process_info)
-{
- using namespace std::placeholders; // For _1, _2, etc.
-
- Error error;
- if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID)
- {
- // If we locate debugserver, keep that located version around
- static FileSpec g_debugserver_file_spec;
-
- ProcessLaunchInfo debugserver_launch_info;
- // Make debugserver run in its own session so signals generated by
- // special terminal key sequences (^C) don't affect debugserver.
- debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
-
- const std::weak_ptr<ProcessGDBRemote> this_wp = std::static_pointer_cast<ProcessGDBRemote>(shared_from_this());
- debugserver_launch_info.SetMonitorProcessCallback(std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4),
- false);
- debugserver_launch_info.SetUserID(process_info.GetUserID());
-
-#if defined (__APPLE__) && (defined (__arm__) || defined (__arm64__) || defined (__aarch64__))
- // On iOS, still do a local connection using a random port
- const char *hostname = "127.0.0.1";
- uint16_t port = get_random_port ();
+#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
+static bool SetCloexecFlag(int fd) {
+#if defined(FD_CLOEXEC)
+ int flags = ::fcntl(fd, F_GETFD);
+ if (flags == -1)
+ return false;
+ return (::fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == 0);
#else
- // Set hostname being NULL to do the reverse connect where debugserver
- // will bind to port zero and it will communicate back to us the port
- // that we will connect to
- const char *hostname = nullptr;
- uint16_t port = 0;
+ return false;
+#endif
+}
#endif
- StreamString url_str;
- const char* url = nullptr;
- if (hostname != nullptr)
- {
- url_str.Printf("%s:%u", hostname, port);
- url = url_str.GetData();
- }
+Error ProcessGDBRemote::LaunchAndConnectToDebugserver(
+ const ProcessInfo &process_info) {
+ using namespace std::placeholders; // For _1, _2, etc.
+
+ Error error;
+ if (m_debugserver_pid == LLDB_INVALID_PROCESS_ID) {
+ // If we locate debugserver, keep that located version around
+ static FileSpec g_debugserver_file_spec;
+
+ ProcessLaunchInfo debugserver_launch_info;
+ // Make debugserver run in its own session so signals generated by
+ // special terminal key sequences (^C) don't affect debugserver.
+ debugserver_launch_info.SetLaunchInSeparateProcessGroup(true);
+
+ const std::weak_ptr<ProcessGDBRemote> this_wp =
+ std::static_pointer_cast<ProcessGDBRemote>(shared_from_this());
+ debugserver_launch_info.SetMonitorProcessCallback(
+ std::bind(MonitorDebugserverProcess, this_wp, _1, _2, _3, _4), false);
+ debugserver_launch_info.SetUserID(process_info.GetUserID());
+
+ int communication_fd = -1;
+#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
+ // Auto close the sockets we might open up unless everything goes OK. This
+ // helps us not leak file descriptors when things go wrong.
+ lldb_utility::CleanUp<int, int> our_socket(-1, -1, close);
+ lldb_utility::CleanUp<int, int> gdb_socket(-1, -1, close);
+
+ // Use a socketpair on Apple for now until other platforms can verify it
+ // works and is fast enough
+ {
+ int sockets[2]; /* the pair of socket descriptors */
+ if (socketpair(AF_UNIX, SOCK_STREAM, 0, sockets) == -1) {
+ error.SetErrorToErrno();
+ return error;
+ }
- error = m_gdb_comm.StartDebugserverProcess (url,
- GetTarget().GetPlatform().get(),
- debugserver_launch_info,
- &port);
+ our_socket.set(sockets[0]);
+ gdb_socket.set(sockets[1]);
+ }
- if (error.Success ())
- m_debugserver_pid = debugserver_launch_info.GetProcessID();
- else
- m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ // Don't let any child processes inherit our communication socket
+ SetCloexecFlag(our_socket.get());
+ communication_fd = gdb_socket.get();
+#endif
- if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
- StartAsyncThread ();
+ error = m_gdb_comm.StartDebugserverProcess(
+ nullptr, GetTarget().GetPlatform().get(), debugserver_launch_info,
+ nullptr, nullptr, communication_fd);
- if (error.Fail())
- {
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
+ if (error.Success())
+ m_debugserver_pid = debugserver_launch_info.GetProcessID();
+ else
+ m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+
+ if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
+#ifdef USE_SOCKETPAIR_FOR_LOCAL_CONNECTION
+ // Our process spawned correctly, we can now set our connection to use our
+ // end of the socket pair
+ m_gdb_comm.SetConnection(
+ new ConnectionFileDescriptor(our_socket.release(), true));
+#endif
+ StartAsyncThread();
+ }
- if (log)
- log->Printf("failed to start debugserver process: %s", error.AsCString());
- return error;
- }
+ if (error.Fail()) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (m_gdb_comm.IsConnected())
- {
- // Finish the connection process by doing the handshake without connecting (send NULL URL)
- ConnectToDebugserver (NULL);
- }
- else
- {
- StreamString connect_url;
- connect_url.Printf("connect://%s:%u", hostname, port);
- error = ConnectToDebugserver (connect_url.GetString().c_str());
- }
+ if (log)
+ log->Printf("failed to start debugserver process: %s",
+ error.AsCString());
+ return error;
+ }
+ if (m_gdb_comm.IsConnected()) {
+ // Finish the connection process by doing the handshake without connecting
+ // (send NULL URL)
+ ConnectToDebugserver("");
+ } else {
+ error.SetErrorString("connection failed");
}
- return error;
+ }
+ return error;
}
-bool
-ProcessGDBRemote::MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t debugserver_pid,
- bool exited, // True if the process did exit
- int signo, // Zero for no signal
- int exit_status // Exit value of process if signal is zero
- )
-{
- // "debugserver_pid" argument passed in is the process ID for
- // debugserver that we are tracking...
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- const bool handled = true;
-
- if (log)
- log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64 ", signo=%i (0x%x), exit_status=%i)", __FUNCTION__,
- debugserver_pid, signo, signo, exit_status);
-
- std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock();
- if (log)
- log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__, static_cast<void *>(process_sp.get()));
- if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid)
- return handled;
-
- // Sleep for a half a second to make sure our inferior process has
- // time to set its exit status before we set it incorrectly when
- // both the debugserver and the inferior process shut down.
- usleep(500000);
- // If our process hasn't yet exited, debugserver might have died.
- // If the process did exit, then we are reaping it.
- const StateType state = process_sp->GetState();
-
- if (state != eStateInvalid && state != eStateUnloaded && state != eStateExited && state != eStateDetached)
- {
- char error_str[1024];
- if (signo)
- {
- const char *signal_cstr = process_sp->GetUnixSignals()->GetSignalAsCString(signo);
- if (signal_cstr)
- ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
- else
- ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with signal %i", signo);
- }
- else
- {
- ::snprintf(error_str, sizeof(error_str), DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x",
- exit_status);
- }
+bool ProcessGDBRemote::MonitorDebugserverProcess(
+ std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t debugserver_pid,
+ bool exited, // True if the process did exit
+ int signo, // Zero for no signal
+ int exit_status // Exit value of process if signal is zero
+ ) {
+ // "debugserver_pid" argument passed in is the process ID for
+ // debugserver that we are tracking...
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ const bool handled = true;
+
+ if (log)
+ log->Printf("ProcessGDBRemote::%s(process_wp, pid=%" PRIu64
+ ", signo=%i (0x%x), exit_status=%i)",
+ __FUNCTION__, debugserver_pid, signo, signo, exit_status);
+
+ std::shared_ptr<ProcessGDBRemote> process_sp = process_wp.lock();
+ if (log)
+ log->Printf("ProcessGDBRemote::%s(process = %p)", __FUNCTION__,
+ static_cast<void *>(process_sp.get()));
+ if (!process_sp || process_sp->m_debugserver_pid != debugserver_pid)
+ return handled;
- process_sp->SetExitStatus(-1, error_str);
+ // Sleep for a half a second to make sure our inferior process has
+ // time to set its exit status before we set it incorrectly when
+ // both the debugserver and the inferior process shut down.
+ usleep(500000);
+ // If our process hasn't yet exited, debugserver might have died.
+ // If the process did exit, then we are reaping it.
+ const StateType state = process_sp->GetState();
+
+ if (state != eStateInvalid && state != eStateUnloaded &&
+ state != eStateExited && state != eStateDetached) {
+ char error_str[1024];
+ if (signo) {
+ const char *signal_cstr =
+ process_sp->GetUnixSignals()->GetSignalAsCString(signo);
+ if (signal_cstr)
+ ::snprintf(error_str, sizeof(error_str),
+ DEBUGSERVER_BASENAME " died with signal %s", signal_cstr);
+ else
+ ::snprintf(error_str, sizeof(error_str),
+ DEBUGSERVER_BASENAME " died with signal %i", signo);
+ } else {
+ ::snprintf(error_str, sizeof(error_str),
+ DEBUGSERVER_BASENAME " died with an exit status of 0x%8.8x",
+ exit_status);
}
- // Debugserver has exited we need to let our ProcessGDBRemote
- // know that it no longer has a debugserver instance
- process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
- return handled;
+
+ process_sp->SetExitStatus(-1, error_str);
+ }
+ // Debugserver has exited we need to let our ProcessGDBRemote
+ // know that it no longer has a debugserver instance
+ process_sp->m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ return handled;
}
-void
-ProcessGDBRemote::KillDebugserverProcess ()
-{
- m_gdb_comm.Disconnect();
- if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID)
- {
- Host::Kill (m_debugserver_pid, SIGINT);
- m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
- }
+void ProcessGDBRemote::KillDebugserverProcess() {
+ m_gdb_comm.Disconnect();
+ if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) {
+ Host::Kill(m_debugserver_pid, SIGINT);
+ m_debugserver_pid = LLDB_INVALID_PROCESS_ID;
+ }
}
-void
-ProcessGDBRemote::Initialize()
-{
- static std::once_flag g_once_flag;
+void ProcessGDBRemote::Initialize() {
+ static std::once_flag g_once_flag;
- std::call_once(g_once_flag, []()
- {
- PluginManager::RegisterPlugin (GetPluginNameStatic(),
- GetPluginDescriptionStatic(),
- CreateInstance,
- DebuggerInitialize);
- });
+ std::call_once(g_once_flag, []() {
+ PluginManager::RegisterPlugin(GetPluginNameStatic(),
+ GetPluginDescriptionStatic(), CreateInstance,
+ DebuggerInitialize);
+ });
}
-void
-ProcessGDBRemote::DebuggerInitialize (Debugger &debugger)
-{
- if (!PluginManager::GetSettingForProcessPlugin(debugger, PluginProperties::GetSettingName()))
- {
- const bool is_global_setting = true;
- PluginManager::CreateSettingForProcessPlugin (debugger,
- GetGlobalPluginProperties()->GetValueProperties(),
- ConstString ("Properties for the gdb-remote process plug-in."),
- is_global_setting);
- }
+void ProcessGDBRemote::DebuggerInitialize(Debugger &debugger) {
+ if (!PluginManager::GetSettingForProcessPlugin(
+ debugger, PluginProperties::GetSettingName())) {
+ const bool is_global_setting = true;
+ PluginManager::CreateSettingForProcessPlugin(
+ debugger, GetGlobalPluginProperties()->GetValueProperties(),
+ ConstString("Properties for the gdb-remote process plug-in."),
+ is_global_setting);
+ }
}
-bool
-ProcessGDBRemote::StartAsyncThread ()
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+bool ProcessGDBRemote::StartAsyncThread() {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
+ if (log)
+ log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__);
- std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
- if (!m_async_thread.IsJoinable())
- {
- // Create a thread that watches our internal state and controls which
- // events make it to clients (into the DCProcess event queue).
+ std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
+ if (!m_async_thread.IsJoinable()) {
+ // Create a thread that watches our internal state and controls which
+ // events make it to clients (into the DCProcess event queue).
- m_async_thread = ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>", ProcessGDBRemote::AsyncThread, this, NULL);
- }
- else if (log)
- log->Printf("ProcessGDBRemote::%s () - Called when Async thread was already running.", __FUNCTION__);
+ m_async_thread =
+ ThreadLauncher::LaunchThread("<lldb.process.gdb-remote.async>",
+ ProcessGDBRemote::AsyncThread, this, NULL);
+ } else if (log)
+ log->Printf("ProcessGDBRemote::%s () - Called when Async thread was "
+ "already running.",
+ __FUNCTION__);
- return m_async_thread.IsJoinable();
+ return m_async_thread.IsJoinable();
}
-void
-ProcessGDBRemote::StopAsyncThread ()
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+void ProcessGDBRemote::StopAsyncThread() {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::%s ()", __FUNCTION__);
+ if (log)
+ log->Printf("ProcessGDBRemote::%s ()", __FUNCTION__);
- std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
- if (m_async_thread.IsJoinable())
- {
- m_async_broadcaster.BroadcastEvent (eBroadcastBitAsyncThreadShouldExit);
+ std::lock_guard<std::recursive_mutex> guard(m_async_thread_state_mutex);
+ if (m_async_thread.IsJoinable()) {
+ m_async_broadcaster.BroadcastEvent(eBroadcastBitAsyncThreadShouldExit);
- // This will shut down the async thread.
- m_gdb_comm.Disconnect(); // Disconnect from the debug server.
+ // This will shut down the async thread.
+ m_gdb_comm.Disconnect(); // Disconnect from the debug server.
- // Stop the stdio thread
- m_async_thread.Join(nullptr);
- m_async_thread.Reset();
- }
- else if (log)
- log->Printf("ProcessGDBRemote::%s () - Called when Async thread was not running.", __FUNCTION__);
+ // Stop the stdio thread
+ m_async_thread.Join(nullptr);
+ m_async_thread.Reset();
+ } else if (log)
+ log->Printf(
+ "ProcessGDBRemote::%s () - Called when Async thread was not running.",
+ __FUNCTION__);
}
-bool
-ProcessGDBRemote::HandleNotifyPacket (StringExtractorGDBRemote &packet)
-{
- // get the packet at a string
- const std::string &pkt = packet.GetStringRef();
- // skip %stop:
- StringExtractorGDBRemote stop_info(pkt.c_str() + 5);
-
- // pass as a thread stop info packet
- SetLastStopPacket(stop_info);
-
- // check for more stop reasons
- HandleStopReplySequence();
-
- // if the process is stopped then we need to fake a resume
- // so that we can stop properly with the new break. This
- // is possible due to SetPrivateState() broadcasting the
- // state change as a side effect.
- if (GetPrivateState() == lldb::StateType::eStateStopped)
- {
- SetPrivateState(lldb::StateType::eStateRunning);
- }
+bool ProcessGDBRemote::HandleNotifyPacket(StringExtractorGDBRemote &packet) {
+ // get the packet at a string
+ const std::string &pkt = packet.GetStringRef();
+ // skip %stop:
+ StringExtractorGDBRemote stop_info(pkt.c_str() + 5);
- // since we have some stopped packets we can halt the process
- SetPrivateState(lldb::StateType::eStateStopped);
+ // pass as a thread stop info packet
+ SetLastStopPacket(stop_info);
- return true;
+ // check for more stop reasons
+ HandleStopReplySequence();
+
+ // if the process is stopped then we need to fake a resume
+ // so that we can stop properly with the new break. This
+ // is possible due to SetPrivateState() broadcasting the
+ // state change as a side effect.
+ if (GetPrivateState() == lldb::StateType::eStateStopped) {
+ SetPrivateState(lldb::StateType::eStateRunning);
+ }
+
+ // since we have some stopped packets we can halt the process
+ SetPrivateState(lldb::StateType::eStateStopped);
+
+ return true;
}
-thread_result_t
-ProcessGDBRemote::AsyncThread (void *arg)
-{
- ProcessGDBRemote *process = (ProcessGDBRemote*) arg;
+thread_result_t ProcessGDBRemote::AsyncThread(void *arg) {
+ ProcessGDBRemote *process = (ProcessGDBRemote *)arg;
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread starting...", __FUNCTION__, arg, process->GetID());
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") thread starting...",
+ __FUNCTION__, arg, process->GetID());
- EventSP event_sp;
- bool done = false;
- while (!done)
- {
+ EventSP event_sp;
+ bool done = false;
+ while (!done) {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") listener.WaitForEvent (NULL, event_sp)...",
+ __FUNCTION__, arg, process->GetID());
+ if (process->m_async_listener_sp->GetEvent(event_sp, llvm::None)) {
+ const uint32_t event_type = event_sp->GetType();
+ if (event_sp->BroadcasterIs(&process->m_async_broadcaster)) {
if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp)...", __FUNCTION__, arg, process->GetID());
- if (process->m_async_listener_sp->WaitForEvent (NULL, event_sp))
- {
- const uint32_t event_type = event_sp->GetType();
- if (event_sp->BroadcasterIs (&process->m_async_broadcaster))
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") Got an event of type: %d...", __FUNCTION__, arg, process->GetID(), event_type);
-
- switch (event_type)
- {
- case eBroadcastBitAsyncContinue:
- {
- const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event_sp.get());
-
- if (continue_packet)
- {
- const char *continue_cstr = (const char *)continue_packet->GetBytes ();
- const size_t continue_cstr_len = continue_packet->GetByteSize ();
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncContinue: %s", __FUNCTION__, arg, process->GetID(), continue_cstr);
-
- if (::strstr (continue_cstr, "vAttach") == NULL)
- process->SetPrivateState(eStateRunning);
- StringExtractorGDBRemote response;
-
- // If in Non-Stop-Mode
- if (process->GetTarget().GetNonStopModeEnabled())
- {
- // send the vCont packet
- if (!process->GetGDBRemote().SendvContPacket(process, continue_cstr, continue_cstr_len, response))
- {
- // Something went wrong
- done = true;
- break;
- }
- }
- // If in All-Stop-Mode
- else
- {
- StateType stop_state = process->GetGDBRemote().SendContinuePacketAndWaitForResponse (process, continue_cstr, continue_cstr_len, response);
-
- // We need to immediately clear the thread ID list so we are sure to get a valid list of threads.
- // The thread ID list might be contained within the "response", or the stop reply packet that
- // caused the stop. So clear it now before we give the stop reply packet to the process
- // using the process->SetLastStopPacket()...
- process->ClearThreadIDList ();
-
- switch (stop_state)
- {
- case eStateStopped:
- case eStateCrashed:
- case eStateSuspended:
- process->SetLastStopPacket (response);
- process->SetPrivateState (stop_state);
- break;
-
- case eStateExited:
- {
- process->SetLastStopPacket (response);
- process->ClearThreadIDList();
- response.SetFilePos(1);
-
- int exit_status = response.GetHexU8();
- const char *desc_cstr = NULL;
- StringExtractor extractor;
- std::string desc_string;
- if (response.GetBytesLeft() > 0 && response.GetChar('-') == ';')
- {
- std::string desc_token;
- while (response.GetNameColonValue (desc_token, desc_string))
- {
- if (desc_token == "description")
- {
- extractor.GetStringRef().swap(desc_string);
- extractor.SetFilePos(0);
- extractor.GetHexByteString (desc_string);
- desc_cstr = desc_string.c_str();
- }
- }
- }
- process->SetExitStatus(exit_status, desc_cstr);
- done = true;
- break;
- }
- case eStateInvalid:
- {
- // Check to see if we were trying to attach and if we got back
- // the "E87" error code from debugserver -- this indicates that
- // the process is not debuggable. Return a slightly more helpful
- // error message about why the attach failed.
- if (::strstr (continue_cstr, "vAttach") != NULL
- && response.GetError() == 0x87)
- {
- process->SetExitStatus(-1, "cannot attach to process due to System Integrity Protection");
- }
- // E01 code from vAttach means that the attach failed
- if (::strstr (continue_cstr, "vAttach") != NULL
- && response.GetError() == 0x1)
- {
- process->SetExitStatus(-1, "unable to attach");
- }
- else
- {
- process->SetExitStatus(-1, "lost connection");
- }
- break;
- }
-
- default:
- process->SetPrivateState (stop_state);
- break;
- } // switch(stop_state)
- } // else // if in All-stop-mode
- } // if (continue_packet)
- } // case eBroadcastBitAysncContinue
- break;
-
- case eBroadcastBitAsyncThreadShouldExit:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got eBroadcastBitAsyncThreadShouldExit...", __FUNCTION__, arg, process->GetID());
- done = true;
- break;
-
- default:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
- done = true;
- break;
- }
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") Got an event of type: %d...",
+ __FUNCTION__, arg, process->GetID(), event_type);
+
+ switch (event_type) {
+ case eBroadcastBitAsyncContinue: {
+ const EventDataBytes *continue_packet =
+ EventDataBytes::GetEventDataFromEvent(event_sp.get());
+
+ if (continue_packet) {
+ const char *continue_cstr =
+ (const char *)continue_packet->GetBytes();
+ const size_t continue_cstr_len = continue_packet->GetByteSize();
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") got eBroadcastBitAsyncContinue: %s",
+ __FUNCTION__, arg, process->GetID(), continue_cstr);
+
+ if (::strstr(continue_cstr, "vAttach") == NULL)
+ process->SetPrivateState(eStateRunning);
+ StringExtractorGDBRemote response;
+
+ // If in Non-Stop-Mode
+ if (process->GetTarget().GetNonStopModeEnabled()) {
+ // send the vCont packet
+ if (!process->GetGDBRemote().SendvContPacket(
+ llvm::StringRef(continue_cstr, continue_cstr_len),
+ response)) {
+ // Something went wrong
+ done = true;
+ break;
+ }
}
- else if (event_sp->BroadcasterIs (&process->m_gdb_comm))
- {
- switch (event_type)
- {
- case Communication::eBroadcastBitReadThreadDidExit:
- process->SetExitStatus (-1, "lost connection");
- done = true;
- break;
-
- case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify:
- {
- lldb_private::Event *event = event_sp.get();
- const EventDataBytes *continue_packet = EventDataBytes::GetEventDataFromEvent(event);
- StringExtractorGDBRemote notify((const char*)continue_packet->GetBytes());
- // Hand this over to the process to handle
- process->HandleNotifyPacket(notify);
- break;
- }
-
- default:
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") got unknown event 0x%8.8x", __FUNCTION__, arg, process->GetID(), event_type);
- done = true;
- break;
+ // If in All-Stop-Mode
+ else {
+ StateType stop_state =
+ process->GetGDBRemote().SendContinuePacketAndWaitForResponse(
+ *process, *process->GetUnixSignals(),
+ llvm::StringRef(continue_cstr, continue_cstr_len),
+ response);
+
+ // We need to immediately clear the thread ID list so we are sure
+ // to get a valid list of threads.
+ // The thread ID list might be contained within the "response", or
+ // the stop reply packet that
+ // caused the stop. So clear it now before we give the stop reply
+ // packet to the process
+ // using the process->SetLastStopPacket()...
+ process->ClearThreadIDList();
+
+ switch (stop_state) {
+ case eStateStopped:
+ case eStateCrashed:
+ case eStateSuspended:
+ process->SetLastStopPacket(response);
+ process->SetPrivateState(stop_state);
+ break;
+
+ case eStateExited: {
+ process->SetLastStopPacket(response);
+ process->ClearThreadIDList();
+ response.SetFilePos(1);
+
+ int exit_status = response.GetHexU8();
+ std::string desc_string;
+ if (response.GetBytesLeft() > 0 &&
+ response.GetChar('-') == ';') {
+ llvm::StringRef desc_str;
+ llvm::StringRef desc_token;
+ while (response.GetNameColonValue(desc_token, desc_str)) {
+ if (desc_token != "description")
+ continue;
+ StringExtractor extractor(desc_str);
+ extractor.GetHexByteString(desc_string);
+ }
}
- }
+ process->SetExitStatus(exit_status, desc_string.c_str());
+ done = true;
+ break;
+ }
+ case eStateInvalid: {
+ // Check to see if we were trying to attach and if we got back
+ // the "E87" error code from debugserver -- this indicates that
+ // the process is not debuggable. Return a slightly more
+ // helpful
+ // error message about why the attach failed.
+ if (::strstr(continue_cstr, "vAttach") != NULL &&
+ response.GetError() == 0x87) {
+ process->SetExitStatus(-1, "cannot attach to process due to "
+ "System Integrity Protection");
+ }
+ // E01 code from vAttach means that the attach failed
+ if (::strstr(continue_cstr, "vAttach") != NULL &&
+ response.GetError() == 0x1) {
+ process->SetExitStatus(-1, "unable to attach");
+ } else {
+ process->SetExitStatus(-1, "lost connection");
+ }
+ break;
+ }
+
+ default:
+ process->SetPrivateState(stop_state);
+ break;
+ } // switch(stop_state)
+ } // else // if in All-stop-mode
+ } // if (continue_packet)
+ } // case eBroadcastBitAysncContinue
+ break;
+
+ case eBroadcastBitAsyncThreadShouldExit:
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") got eBroadcastBitAsyncThreadShouldExit...",
+ __FUNCTION__, arg, process->GetID());
+ done = true;
+ break;
+
+ default:
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") got unknown event 0x%8.8x",
+ __FUNCTION__, arg, process->GetID(), event_type);
+ done = true;
+ break;
}
- else
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") listener.WaitForEvent (NULL, event_sp) => false", __FUNCTION__, arg, process->GetID());
- done = true;
+ } else if (event_sp->BroadcasterIs(&process->m_gdb_comm)) {
+ switch (event_type) {
+ case Communication::eBroadcastBitReadThreadDidExit:
+ process->SetExitStatus(-1, "lost connection");
+ done = true;
+ break;
+
+ case GDBRemoteCommunication::eBroadcastBitGdbReadThreadGotNotify: {
+ lldb_private::Event *event = event_sp.get();
+ const EventDataBytes *continue_packet =
+ EventDataBytes::GetEventDataFromEvent(event);
+ StringExtractorGDBRemote notify(
+ (const char *)continue_packet->GetBytes());
+ // Hand this over to the process to handle
+ process->HandleNotifyPacket(notify);
+ break;
+ }
+
+ default:
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") got unknown event 0x%8.8x",
+ __FUNCTION__, arg, process->GetID(), event_type);
+ done = true;
+ break;
}
+ }
+ } else {
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") listener.WaitForEvent (NULL, event_sp) => false",
+ __FUNCTION__, arg, process->GetID());
+ done = true;
}
+ }
- if (log)
- log->Printf ("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64 ") thread exiting...", __FUNCTION__, arg, process->GetID());
+ if (log)
+ log->Printf("ProcessGDBRemote::%s (arg = %p, pid = %" PRIu64
+ ") thread exiting...",
+ __FUNCTION__, arg, process->GetID());
- return NULL;
+ return NULL;
}
-//uint32_t
-//ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList &matches, std::vector<lldb::pid_t> &pids)
+// uint32_t
+// ProcessGDBRemote::ListProcessesMatchingName (const char *name, StringList
+// &matches, std::vector<lldb::pid_t> &pids)
//{
-// // If we are planning to launch the debugserver remotely, then we need to fire up a debugserver
-// // process and ask it for the list of processes. But if we are local, we can let the Host do it.
+// // If we are planning to launch the debugserver remotely, then we need to
+// fire up a debugserver
+// // process and ask it for the list of processes. But if we are local, we
+// can let the Host do it.
// if (m_local_debugserver)
// {
// return Host::ListProcessesMatchingName (name, matches, pids);
@@ -4070,189 +3729,240 @@ ProcessGDBRemote::AsyncThread (void *arg)
//
//}
//
-bool
-ProcessGDBRemote::NewThreadNotifyBreakpointHit (void *baton,
- StoppointCallbackContext *context,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id)
-{
- // I don't think I have to do anything here, just make sure I notice the new thread when it starts to
- // run so I can stop it if that's what I want to do.
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (log)
- log->Printf("Hit New Thread Notification breakpoint.");
- return false;
+bool ProcessGDBRemote::NewThreadNotifyBreakpointHit(
+ void *baton, StoppointCallbackContext *context, lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id) {
+ // I don't think I have to do anything here, just make sure I notice the new
+ // thread when it starts to
+ // run so I can stop it if that's what I want to do.
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (log)
+ log->Printf("Hit New Thread Notification breakpoint.");
+ return false;
}
-
-bool
-ProcessGDBRemote::StartNoticingNewThreads()
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (m_thread_create_bp_sp)
- {
+bool ProcessGDBRemote::StartNoticingNewThreads() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (m_thread_create_bp_sp) {
+ if (log && log->GetVerbose())
+ log->Printf("Enabled noticing new thread breakpoint.");
+ m_thread_create_bp_sp->SetEnabled(true);
+ } else {
+ PlatformSP platform_sp(GetTarget().GetPlatform());
+ if (platform_sp) {
+ m_thread_create_bp_sp =
+ platform_sp->SetThreadCreationBreakpoint(GetTarget());
+ if (m_thread_create_bp_sp) {
if (log && log->GetVerbose())
- log->Printf("Enabled noticing new thread breakpoint.");
- m_thread_create_bp_sp->SetEnabled(true);
- }
- else
- {
- PlatformSP platform_sp (GetTarget().GetPlatform());
- if (platform_sp)
- {
- m_thread_create_bp_sp = platform_sp->SetThreadCreationBreakpoint(GetTarget());
- if (m_thread_create_bp_sp)
- {
- if (log && log->GetVerbose())
- log->Printf("Successfully created new thread notification breakpoint %i", m_thread_create_bp_sp->GetID());
- m_thread_create_bp_sp->SetCallback (ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
- }
- else
- {
- if (log)
- log->Printf("Failed to create new thread notification breakpoint.");
- }
- }
+ log->Printf(
+ "Successfully created new thread notification breakpoint %i",
+ m_thread_create_bp_sp->GetID());
+ m_thread_create_bp_sp->SetCallback(
+ ProcessGDBRemote::NewThreadNotifyBreakpointHit, this, true);
+ } else {
+ if (log)
+ log->Printf("Failed to create new thread notification breakpoint.");
+ }
}
- return m_thread_create_bp_sp.get() != NULL;
+ }
+ return m_thread_create_bp_sp.get() != NULL;
}
-bool
-ProcessGDBRemote::StopNoticingNewThreads()
-{
- Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
- if (log && log->GetVerbose())
- log->Printf ("Disabling new thread notification breakpoint.");
+bool ProcessGDBRemote::StopNoticingNewThreads() {
+ Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP));
+ if (log && log->GetVerbose())
+ log->Printf("Disabling new thread notification breakpoint.");
- if (m_thread_create_bp_sp)
- m_thread_create_bp_sp->SetEnabled(false);
+ if (m_thread_create_bp_sp)
+ m_thread_create_bp_sp->SetEnabled(false);
- return true;
+ return true;
}
-DynamicLoader *
-ProcessGDBRemote::GetDynamicLoader ()
-{
- if (m_dyld_ap.get() == NULL)
- m_dyld_ap.reset (DynamicLoader::FindPlugin(this, NULL));
- return m_dyld_ap.get();
+DynamicLoader *ProcessGDBRemote::GetDynamicLoader() {
+ if (m_dyld_ap.get() == NULL)
+ m_dyld_ap.reset(DynamicLoader::FindPlugin(this, NULL));
+ return m_dyld_ap.get();
}
-Error
-ProcessGDBRemote::SendEventData(const char *data)
-{
- int return_value;
- bool was_supported;
+Error ProcessGDBRemote::SendEventData(const char *data) {
+ int return_value;
+ bool was_supported;
- Error error;
+ Error error;
- return_value = m_gdb_comm.SendLaunchEventDataPacket (data, &was_supported);
- if (return_value != 0)
- {
- if (!was_supported)
- error.SetErrorString("Sending events is not supported for this process.");
- else
- error.SetErrorStringWithFormat("Error sending event data: %d.", return_value);
- }
- return error;
+ return_value = m_gdb_comm.SendLaunchEventDataPacket(data, &was_supported);
+ if (return_value != 0) {
+ if (!was_supported)
+ error.SetErrorString("Sending events is not supported for this process.");
+ else
+ error.SetErrorStringWithFormat("Error sending event data: %d.",
+ return_value);
+ }
+ return error;
}
-const DataBufferSP
-ProcessGDBRemote::GetAuxvData()
-{
- DataBufferSP buf;
- if (m_gdb_comm.GetQXferAuxvReadSupported())
- {
- std::string response_string;
- if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::", response_string) == GDBRemoteCommunication::PacketResult::Success)
- buf.reset(new DataBufferHeap(response_string.c_str(), response_string.length()));
- }
- return buf;
+const DataBufferSP ProcessGDBRemote::GetAuxvData() {
+ DataBufferSP buf;
+ if (m_gdb_comm.GetQXferAuxvReadSupported()) {
+ std::string response_string;
+ if (m_gdb_comm.SendPacketsAndConcatenateResponses("qXfer:auxv:read::",
+ response_string) ==
+ GDBRemoteCommunication::PacketResult::Success)
+ buf.reset(new DataBufferHeap(response_string.c_str(),
+ response_string.length()));
+ }
+ return buf;
}
StructuredData::ObjectSP
-ProcessGDBRemote::GetExtendedInfoForThread (lldb::tid_t tid)
-{
- StructuredData::ObjectSP object_sp;
+ProcessGDBRemote::GetExtendedInfoForThread(lldb::tid_t tid) {
+ StructuredData::ObjectSP object_sp;
- if (m_gdb_comm.GetThreadExtendedInfoSupported())
- {
- StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
- SystemRuntime *runtime = GetSystemRuntime();
- if (runtime)
- {
- runtime->AddThreadExtendedInfoPacketHints (args_dict);
- }
- args_dict->GetAsDictionary()->AddIntegerItem ("thread", tid);
+ if (m_gdb_comm.GetThreadExtendedInfoSupported()) {
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+ SystemRuntime *runtime = GetSystemRuntime();
+ if (runtime) {
+ runtime->AddThreadExtendedInfoPacketHints(args_dict);
+ }
+ args_dict->GetAsDictionary()->AddIntegerItem("thread", tid);
- StreamString packet;
- packet << "jThreadExtendedInfo:";
- args_dict->Dump (packet);
+ StreamString packet;
+ packet << "jThreadExtendedInfo:";
+ args_dict->Dump(packet, false);
- // FIXME the final character of a JSON dictionary, '}', is the escape
- // character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
- packet << (char) (0x7d ^ 0x20);
+ // FIXME the final character of a JSON dictionary, '}', is the escape
+ // character in gdb-remote binary mode. lldb currently doesn't escape
+ // these characters in its packet output -- so we add the quoted version
+ // of the } character here manually in case we talk to a debugserver which
+ // un-escapes the characters at packet read time.
+ packet << (char)(0x7d ^ 0x20);
- StringExtractorGDBRemote response;
- response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success)
- {
- StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType();
- if (response_type == StringExtractorGDBRemote::eResponse)
- {
- if (!response.Empty())
- {
- object_sp = StructuredData::ParseJSON (response.GetStringRef());
- }
- }
+ StringExtractorGDBRemote response;
+ response.SetResponseValidatorToJSON();
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
+ false) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ StringExtractorGDBRemote::ResponseType response_type =
+ response.GetResponseType();
+ if (response_type == StringExtractorGDBRemote::eResponse) {
+ if (!response.Empty()) {
+ object_sp = StructuredData::ParseJSON(response.GetStringRef());
}
+ }
}
- return object_sp;
+ }
+ return object_sp;
+}
+
+StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos(
+ lldb::addr_t image_list_address, lldb::addr_t image_count) {
+
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+ args_dict->GetAsDictionary()->AddIntegerItem("image_list_address",
+ image_list_address);
+ args_dict->GetAsDictionary()->AddIntegerItem("image_count", image_count);
+
+ return GetLoadedDynamicLibrariesInfos_sender(args_dict);
+}
+
+StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos() {
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+
+ args_dict->GetAsDictionary()->AddBooleanItem("fetch_all_solibs", true);
+
+ return GetLoadedDynamicLibrariesInfos_sender(args_dict);
+}
+
+StructuredData::ObjectSP ProcessGDBRemote::GetLoadedDynamicLibrariesInfos(
+ const std::vector<lldb::addr_t> &load_addresses) {
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+ StructuredData::ArraySP addresses(new StructuredData::Array);
+
+ for (auto addr : load_addresses) {
+ StructuredData::ObjectSP addr_sp(new StructuredData::Integer(addr));
+ addresses->AddItem(addr_sp);
+ }
+
+ args_dict->GetAsDictionary()->AddItem("solib_addresses", addresses);
+
+ return GetLoadedDynamicLibrariesInfos_sender(args_dict);
}
StructuredData::ObjectSP
-ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count)
-{
- StructuredData::ObjectSP object_sp;
+ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender(
+ StructuredData::ObjectSP args_dict) {
+ StructuredData::ObjectSP object_sp;
- if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported())
- {
- // Scope for the scoped timeout object
- GDBRemoteCommunication::ScopedTimeout timeout (m_gdb_comm, 10);
+ if (m_gdb_comm.GetLoadedDynamicLibrariesInfosSupported()) {
+ // Scope for the scoped timeout object
+ GDBRemoteCommunication::ScopedTimeout timeout(m_gdb_comm,
+ std::chrono::seconds(10));
- StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
- args_dict->GetAsDictionary()->AddIntegerItem ("image_list_address", image_list_address);
- args_dict->GetAsDictionary()->AddIntegerItem ("image_count", image_count);
+ StreamString packet;
+ packet << "jGetLoadedDynamicLibrariesInfos:";
+ args_dict->Dump(packet, false);
- StreamString packet;
- packet << "jGetLoadedDynamicLibrariesInfos:";
- args_dict->Dump (packet);
+ // FIXME the final character of a JSON dictionary, '}', is the escape
+ // character in gdb-remote binary mode. lldb currently doesn't escape
+ // these characters in its packet output -- so we add the quoted version
+ // of the } character here manually in case we talk to a debugserver which
+ // un-escapes the characters at packet read time.
+ packet << (char)(0x7d ^ 0x20);
- // FIXME the final character of a JSON dictionary, '}', is the escape
- // character in gdb-remote binary mode. lldb currently doesn't escape
- // these characters in its packet output -- so we add the quoted version
- // of the } character here manually in case we talk to a debugserver which
- // un-escapes the characters at packet read time.
- packet << (char) (0x7d ^ 0x20);
+ StringExtractorGDBRemote response;
+ response.SetResponseValidatorToJSON();
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
+ false) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ StringExtractorGDBRemote::ResponseType response_type =
+ response.GetResponseType();
+ if (response_type == StringExtractorGDBRemote::eResponse) {
+ if (!response.Empty()) {
+ object_sp = StructuredData::ParseJSON(response.GetStringRef());
+ }
+ }
+ }
+ }
+ return object_sp;
+}
- StringExtractorGDBRemote response;
- response.SetResponseValidatorToJSON();
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success)
- {
- StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType();
- if (response_type == StringExtractorGDBRemote::eResponse)
- {
- if (!response.Empty())
- {
- object_sp = StructuredData::ParseJSON (response.GetStringRef());
- }
- }
+StructuredData::ObjectSP ProcessGDBRemote::GetSharedCacheInfo() {
+ StructuredData::ObjectSP object_sp;
+ StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
+
+ if (m_gdb_comm.GetSharedCacheInfoSupported()) {
+ StreamString packet;
+ packet << "jGetSharedCacheInfo:";
+ args_dict->Dump(packet, false);
+
+ // FIXME the final character of a JSON dictionary, '}', is the escape
+ // character in gdb-remote binary mode. lldb currently doesn't escape
+ // these characters in its packet output -- so we add the quoted version
+ // of the } character here manually in case we talk to a debugserver which
+ // un-escapes the characters at packet read time.
+ packet << (char)(0x7d ^ 0x20);
+
+ StringExtractorGDBRemote response;
+ response.SetResponseValidatorToJSON();
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
+ false) ==
+ GDBRemoteCommunication::PacketResult::Success) {
+ StringExtractorGDBRemote::ResponseType response_type =
+ response.GetResponseType();
+ if (response_type == StringExtractorGDBRemote::eResponse) {
+ if (!response.Empty()) {
+ object_sp = StructuredData::ParseJSON(response.GetStringRef());
}
+ }
}
- return object_sp;
+ }
+ return object_sp;
+}
+
+Error ProcessGDBRemote::ConfigureStructuredData(
+ const ConstString &type_name, const StructuredData::ObjectSP &config_sp) {
+ return m_gdb_comm.ConfigureRemoteStructuredData(type_name, config_sp);
}
// Establish the largest memory read/write payloads we should use.
@@ -4264,100 +3974,103 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_addres
// If the remote stub doesn't advertise a max packet size, use a
// conservative default.
-void
-ProcessGDBRemote::GetMaxMemorySize()
-{
- const uint64_t reasonable_largeish_default = 128 * 1024;
- const uint64_t conservative_default = 512;
+void ProcessGDBRemote::GetMaxMemorySize() {
+ const uint64_t reasonable_largeish_default = 128 * 1024;
+ const uint64_t conservative_default = 512;
- if (m_max_memory_size == 0)
- {
- uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize();
- if (stub_max_size != UINT64_MAX && stub_max_size != 0)
- {
- // Save the stub's claimed maximum packet size
- m_remote_stub_max_memory_size = stub_max_size;
+ if (m_max_memory_size == 0) {
+ uint64_t stub_max_size = m_gdb_comm.GetRemoteMaxPacketSize();
+ if (stub_max_size != UINT64_MAX && stub_max_size != 0) {
+ // Save the stub's claimed maximum packet size
+ m_remote_stub_max_memory_size = stub_max_size;
- // Even if the stub says it can support ginormous packets,
- // don't exceed our reasonable largeish default packet size.
- if (stub_max_size > reasonable_largeish_default)
- {
- stub_max_size = reasonable_largeish_default;
- }
+ // Even if the stub says it can support ginormous packets,
+ // don't exceed our reasonable largeish default packet size.
+ if (stub_max_size > reasonable_largeish_default) {
+ stub_max_size = reasonable_largeish_default;
+ }
- m_max_memory_size = stub_max_size;
- }
- else
- {
- m_max_memory_size = conservative_default;
- }
+ m_max_memory_size = stub_max_size;
+ } else {
+ m_max_memory_size = conservative_default;
}
+ }
}
-void
-ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max)
-{
- if (user_specified_max != 0)
- {
- GetMaxMemorySize ();
-
- if (m_remote_stub_max_memory_size != 0)
- {
- if (m_remote_stub_max_memory_size < user_specified_max)
- {
- m_max_memory_size = m_remote_stub_max_memory_size; // user specified a packet size too big, go as big
- // as the remote stub says we can go.
- }
- else
- {
- m_max_memory_size = user_specified_max; // user's packet size is good
- }
- }
- else
- {
- m_max_memory_size = user_specified_max; // user's packet size is probably fine
- }
+void ProcessGDBRemote::SetUserSpecifiedMaxMemoryTransferSize(
+ uint64_t user_specified_max) {
+ if (user_specified_max != 0) {
+ GetMaxMemorySize();
+
+ if (m_remote_stub_max_memory_size != 0) {
+ if (m_remote_stub_max_memory_size < user_specified_max) {
+ m_max_memory_size = m_remote_stub_max_memory_size; // user specified a
+ // packet size too
+ // big, go as big
+ // as the remote stub says we can go.
+ } else {
+ m_max_memory_size = user_specified_max; // user's packet size is good
+ }
+ } else {
+ m_max_memory_size =
+ user_specified_max; // user's packet size is probably fine
}
+ }
}
-bool
-ProcessGDBRemote::GetModuleSpec(const FileSpec& module_file_spec,
- const ArchSpec& arch,
- ModuleSpec &module_spec)
-{
- Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM);
+bool ProcessGDBRemote::GetModuleSpec(const FileSpec &module_file_spec,
+ const ArchSpec &arch,
+ ModuleSpec &module_spec) {
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM);
- if (!m_gdb_comm.GetModuleInfo (module_file_spec, arch, module_spec))
- {
- if (log)
- log->Printf ("ProcessGDBRemote::%s - failed to get module info for %s:%s",
- __FUNCTION__, module_file_spec.GetPath ().c_str (),
- arch.GetTriple ().getTriple ().c_str ());
- return false;
- }
+ const ModuleCacheKey key(module_file_spec.GetPath(),
+ arch.GetTriple().getTriple());
+ auto cached = m_cached_module_specs.find(key);
+ if (cached != m_cached_module_specs.end()) {
+ module_spec = cached->second;
+ return bool(module_spec);
+ }
+ if (!m_gdb_comm.GetModuleInfo(module_file_spec, arch, module_spec)) {
if (log)
- {
- StreamString stream;
- module_spec.Dump (stream);
- log->Printf ("ProcessGDBRemote::%s - got module info for (%s:%s) : %s",
- __FUNCTION__, module_file_spec.GetPath ().c_str (),
- arch.GetTriple ().getTriple ().c_str (), stream.GetString ().c_str ());
- }
+ log->Printf("ProcessGDBRemote::%s - failed to get module info for %s:%s",
+ __FUNCTION__, module_file_spec.GetPath().c_str(),
+ arch.GetTriple().getTriple().c_str());
+ return false;
+ }
+
+ if (log) {
+ StreamString stream;
+ module_spec.Dump(stream);
+ log->Printf("ProcessGDBRemote::%s - got module info for (%s:%s) : %s",
+ __FUNCTION__, module_file_spec.GetPath().c_str(),
+ arch.GetTriple().getTriple().c_str(), stream.GetData());
+ }
+
+ m_cached_module_specs[key] = module_spec;
+ return true;
+}
- return true;
+void ProcessGDBRemote::PrefetchModuleSpecs(
+ llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) {
+ auto module_specs = m_gdb_comm.GetModulesInfo(module_file_specs, triple);
+ if (module_specs) {
+ for (const FileSpec &spec : module_file_specs)
+ m_cached_module_specs[ModuleCacheKey(spec.GetPath(),
+ triple.getTriple())] = ModuleSpec();
+ for (const ModuleSpec &spec : *module_specs)
+ m_cached_module_specs[ModuleCacheKey(spec.GetFileSpec().GetPath(),
+ triple.getTriple())] = spec;
+ }
}
-bool
-ProcessGDBRemote::GetHostOSVersion(uint32_t &major,
- uint32_t &minor,
- uint32_t &update)
-{
- if (m_gdb_comm.GetOSVersion(major, minor, update))
- return true;
- // We failed to get the host OS version, defer to the base
- // implementation to correctly invalidate the arguments.
- return Process::GetHostOSVersion(major, minor, update);
+bool ProcessGDBRemote::GetHostOSVersion(uint32_t &major, uint32_t &minor,
+ uint32_t &update) {
+ if (m_gdb_comm.GetOSVersion(major, minor, update))
+ return true;
+ // We failed to get the host OS version, defer to the base
+ // implementation to correctly invalidate the arguments.
+ return Process::GetHostOSVersion(major, minor, update);
}
namespace {
@@ -4365,29 +4078,29 @@ namespace {
typedef std::vector<std::string> stringVec;
typedef std::vector<struct GdbServerRegisterInfo> GDBServerRegisterVec;
-struct RegisterSetInfo
-{
- ConstString name;
+struct RegisterSetInfo {
+ ConstString name;
};
typedef std::map<uint32_t, RegisterSetInfo> RegisterSetMap;
-struct GdbServerTargetInfo
-{
- std::string arch;
- std::string osabi;
- stringVec includes;
- RegisterSetMap reg_set_map;
- XMLNode feature_node;
+struct GdbServerTargetInfo {
+ std::string arch;
+ std::string osabi;
+ stringVec includes;
+ RegisterSetMap reg_set_map;
+ XMLNode feature_node;
};
-bool
-ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp, uint32_t &cur_reg_num, uint32_t &reg_offset)
-{
- if (!feature_node)
- return false;
+bool ParseRegisters(XMLNode feature_node, GdbServerTargetInfo &target_info,
+ GDBRemoteDynamicRegisterInfo &dyn_reg_info, ABISP abi_sp,
+ uint32_t &cur_reg_num, uint32_t &reg_offset) {
+ if (!feature_node)
+ return false;
- feature_node.ForEachChildElementWithName("reg", [&target_info, &dyn_reg_info, &cur_reg_num, &reg_offset, &abi_sp](const XMLNode &reg_node) -> bool {
+ feature_node.ForEachChildElementWithName(
+ "reg", [&target_info, &dyn_reg_info, &cur_reg_num, &reg_offset,
+ &abi_sp](const XMLNode &reg_node) -> bool {
std::string gdb_group;
std::string gdb_type;
ConstString reg_name;
@@ -4398,931 +4111,1038 @@ ParseRegisters (XMLNode feature_node, GdbServerTargetInfo &target_info, GDBRemot
std::vector<uint8_t> dwarf_opcode_bytes;
bool encoding_set = false;
bool format_set = false;
- RegisterInfo reg_info = { NULL, // Name
- NULL, // Alt name
- 0, // byte size
- reg_offset, // offset
- eEncodingUint, // encoding
- eFormatHex, // format
+ RegisterInfo reg_info = {
+ NULL, // Name
+ NULL, // Alt name
+ 0, // byte size
+ reg_offset, // offset
+ eEncodingUint, // encoding
+ eFormatHex, // format
{
LLDB_INVALID_REGNUM, // eh_frame reg num
LLDB_INVALID_REGNUM, // DWARF reg num
LLDB_INVALID_REGNUM, // generic reg num
- cur_reg_num, // process plugin reg num
- cur_reg_num // native register number
+ cur_reg_num, // process plugin reg num
+ cur_reg_num // native register number
},
NULL,
NULL,
- NULL, // Dwarf Expression opcode bytes pointer
- 0 // Dwarf Expression opcode bytes length
+ NULL, // Dwarf Expression opcode bytes pointer
+ 0 // Dwarf Expression opcode bytes length
};
- reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type, &reg_name, &alt_name, &set_name, &value_regs, &invalidate_regs, &encoding_set, &format_set, &reg_info, &cur_reg_num, &reg_offset, &dwarf_opcode_bytes](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
- if (name == "name")
- {
- reg_name.SetString(value);
- }
- else if (name == "bitsize")
- {
- reg_info.byte_size = StringConvert::ToUInt32(value.data(), 0, 0) / CHAR_BIT;
- }
- else if (name == "type")
- {
- gdb_type = value.str();
- }
- else if (name == "group")
- {
- gdb_group = value.str();
- }
- else if (name == "regnum")
- {
- const uint32_t regnum = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
- if (regnum != LLDB_INVALID_REGNUM)
- {
- reg_info.kinds[eRegisterKindProcessPlugin] = regnum;
- }
- }
- else if (name == "offset")
- {
- reg_offset = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
- }
- else if (name == "altname")
- {
- alt_name.SetString(value);
- }
- else if (name == "encoding")
- {
- encoding_set = true;
- reg_info.encoding = Args::StringToEncoding (value.data(), eEncodingUint);
- }
- else if (name == "format")
- {
- format_set = true;
- Format format = eFormatInvalid;
- if (Args::StringToFormat (value.data(), format, NULL).Success())
- reg_info.format = format;
- else if (value == "vector-sint8")
- reg_info.format = eFormatVectorOfSInt8;
- else if (value == "vector-uint8")
- reg_info.format = eFormatVectorOfUInt8;
- else if (value == "vector-sint16")
- reg_info.format = eFormatVectorOfSInt16;
- else if (value == "vector-uint16")
- reg_info.format = eFormatVectorOfUInt16;
- else if (value == "vector-sint32")
- reg_info.format = eFormatVectorOfSInt32;
- else if (value == "vector-uint32")
- reg_info.format = eFormatVectorOfUInt32;
- else if (value == "vector-float32")
- reg_info.format = eFormatVectorOfFloat32;
- else if (value == "vector-uint128")
- reg_info.format = eFormatVectorOfUInt128;
- }
- else if (name == "group_id")
- {
- const uint32_t set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
- RegisterSetMap::const_iterator pos = target_info.reg_set_map.find(set_id);
- if (pos != target_info.reg_set_map.end())
- set_name = pos->second.name;
- }
- else if (name == "gcc_regnum" || name == "ehframe_regnum")
- {
- reg_info.kinds[eRegisterKindEHFrame] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
- }
- else if (name == "dwarf_regnum")
- {
- reg_info.kinds[eRegisterKindDWARF] = StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
- }
- else if (name == "generic")
- {
- reg_info.kinds[eRegisterKindGeneric] = Args::StringToGenericRegister(value.data());
- }
- else if (name == "value_regnums")
- {
- SplitCommaSeparatedRegisterNumberString(value, value_regs, 0);
- }
- else if (name == "invalidate_regnums")
- {
- SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0);
- }
- else if (name == "dynamic_size_dwarf_expr_bytes")
- {
- StringExtractor opcode_extractor;
- std::string opcode_string = value.str ();
- size_t dwarf_opcode_len = opcode_string.length () / 2;
- assert (dwarf_opcode_len > 0);
-
- dwarf_opcode_bytes.resize (dwarf_opcode_len);
- reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
- opcode_extractor.GetStringRef ().swap (opcode_string);
- uint32_t ret_val = opcode_extractor.GetHexBytesAvail (dwarf_opcode_bytes.data (),
- dwarf_opcode_len);
- assert (dwarf_opcode_len == ret_val);
-
- reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data ();
- }
- else
- {
- printf("unhandled attribute %s = %s\n", name.data(), value.data());
+ reg_node.ForEachAttribute([&target_info, &gdb_group, &gdb_type,
+ &reg_name, &alt_name, &set_name, &value_regs,
+ &invalidate_regs, &encoding_set, &format_set,
+ &reg_info, &cur_reg_num, &reg_offset,
+ &dwarf_opcode_bytes](
+ const llvm::StringRef &name,
+ const llvm::StringRef &value) -> bool {
+ if (name == "name") {
+ reg_name.SetString(value);
+ } else if (name == "bitsize") {
+ reg_info.byte_size =
+ StringConvert::ToUInt32(value.data(), 0, 0) / CHAR_BIT;
+ } else if (name == "type") {
+ gdb_type = value.str();
+ } else if (name == "group") {
+ gdb_group = value.str();
+ } else if (name == "regnum") {
+ const uint32_t regnum =
+ StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
+ if (regnum != LLDB_INVALID_REGNUM) {
+ reg_info.kinds[eRegisterKindProcessPlugin] = regnum;
}
- return true; // Keep iterating through all attributes
+ } else if (name == "offset") {
+ reg_offset = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
+ } else if (name == "altname") {
+ alt_name.SetString(value);
+ } else if (name == "encoding") {
+ encoding_set = true;
+ reg_info.encoding = Args::StringToEncoding(value, eEncodingUint);
+ } else if (name == "format") {
+ format_set = true;
+ Format format = eFormatInvalid;
+ if (Args::StringToFormat(value.data(), format, NULL).Success())
+ reg_info.format = format;
+ else if (value == "vector-sint8")
+ reg_info.format = eFormatVectorOfSInt8;
+ else if (value == "vector-uint8")
+ reg_info.format = eFormatVectorOfUInt8;
+ else if (value == "vector-sint16")
+ reg_info.format = eFormatVectorOfSInt16;
+ else if (value == "vector-uint16")
+ reg_info.format = eFormatVectorOfUInt16;
+ else if (value == "vector-sint32")
+ reg_info.format = eFormatVectorOfSInt32;
+ else if (value == "vector-uint32")
+ reg_info.format = eFormatVectorOfUInt32;
+ else if (value == "vector-float32")
+ reg_info.format = eFormatVectorOfFloat32;
+ else if (value == "vector-uint64")
+ reg_info.format = eFormatVectorOfUInt64;
+ else if (value == "vector-uint128")
+ reg_info.format = eFormatVectorOfUInt128;
+ } else if (name == "group_id") {
+ const uint32_t set_id =
+ StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
+ RegisterSetMap::const_iterator pos =
+ target_info.reg_set_map.find(set_id);
+ if (pos != target_info.reg_set_map.end())
+ set_name = pos->second.name;
+ } else if (name == "gcc_regnum" || name == "ehframe_regnum") {
+ reg_info.kinds[eRegisterKindEHFrame] =
+ StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
+ } else if (name == "dwarf_regnum") {
+ reg_info.kinds[eRegisterKindDWARF] =
+ StringConvert::ToUInt32(value.data(), LLDB_INVALID_REGNUM, 0);
+ } else if (name == "generic") {
+ reg_info.kinds[eRegisterKindGeneric] =
+ Args::StringToGenericRegister(value);
+ } else if (name == "value_regnums") {
+ SplitCommaSeparatedRegisterNumberString(value, value_regs, 0);
+ } else if (name == "invalidate_regnums") {
+ SplitCommaSeparatedRegisterNumberString(value, invalidate_regs, 0);
+ } else if (name == "dynamic_size_dwarf_expr_bytes") {
+ StringExtractor opcode_extractor;
+ std::string opcode_string = value.str();
+ size_t dwarf_opcode_len = opcode_string.length() / 2;
+ assert(dwarf_opcode_len > 0);
+
+ dwarf_opcode_bytes.resize(dwarf_opcode_len);
+ reg_info.dynamic_size_dwarf_len = dwarf_opcode_len;
+ opcode_extractor.GetStringRef().swap(opcode_string);
+ uint32_t ret_val =
+ opcode_extractor.GetHexBytesAvail(dwarf_opcode_bytes);
+ assert(dwarf_opcode_len == ret_val);
+
+ reg_info.dynamic_size_dwarf_expr_bytes = dwarf_opcode_bytes.data();
+ } else {
+ printf("unhandled attribute %s = %s\n", name.data(), value.data());
+ }
+ return true; // Keep iterating through all attributes
});
- if (!gdb_type.empty() && !(encoding_set || format_set))
- {
- if (gdb_type.find("int") == 0)
- {
- reg_info.format = eFormatHex;
- reg_info.encoding = eEncodingUint;
- }
- else if (gdb_type == "data_ptr" || gdb_type == "code_ptr")
- {
- reg_info.format = eFormatAddressInfo;
- reg_info.encoding = eEncodingUint;
- }
- else if (gdb_type == "i387_ext" || gdb_type == "float")
- {
- reg_info.format = eFormatFloat;
- reg_info.encoding = eEncodingIEEE754;
- }
+ if (!gdb_type.empty() && !(encoding_set || format_set)) {
+ if (gdb_type.find("int") == 0) {
+ reg_info.format = eFormatHex;
+ reg_info.encoding = eEncodingUint;
+ } else if (gdb_type == "data_ptr" || gdb_type == "code_ptr") {
+ reg_info.format = eFormatAddressInfo;
+ reg_info.encoding = eEncodingUint;
+ } else if (gdb_type == "i387_ext" || gdb_type == "float") {
+ reg_info.format = eFormatFloat;
+ reg_info.encoding = eEncodingIEEE754;
+ }
}
- // Only update the register set name if we didn't get a "reg_set" attribute.
+ // Only update the register set name if we didn't get a "reg_set"
+ // attribute.
// "set_name" will be empty if we didn't have a "reg_set" attribute.
if (!set_name && !gdb_group.empty())
- set_name.SetCString(gdb_group.c_str());
+ set_name.SetCString(gdb_group.c_str());
reg_info.byte_offset = reg_offset;
- assert (reg_info.byte_size != 0);
+ assert(reg_info.byte_size != 0);
reg_offset += reg_info.byte_size;
- if (!value_regs.empty())
- {
- value_regs.push_back(LLDB_INVALID_REGNUM);
- reg_info.value_regs = value_regs.data();
+ if (!value_regs.empty()) {
+ value_regs.push_back(LLDB_INVALID_REGNUM);
+ reg_info.value_regs = value_regs.data();
}
- if (!invalidate_regs.empty())
- {
- invalidate_regs.push_back(LLDB_INVALID_REGNUM);
- reg_info.invalidate_regs = invalidate_regs.data();
+ if (!invalidate_regs.empty()) {
+ invalidate_regs.push_back(LLDB_INVALID_REGNUM);
+ reg_info.invalidate_regs = invalidate_regs.data();
}
++cur_reg_num;
- AugmentRegisterInfoViaABI (reg_info, reg_name, abi_sp);
+ AugmentRegisterInfoViaABI(reg_info, reg_name, abi_sp);
dyn_reg_info.AddRegister(reg_info, reg_name, alt_name, set_name);
return true; // Keep iterating through all "reg" elements
- });
- return true;
+ });
+ return true;
}
} // namespace {}
-
// query the target of gdb-remote for extended target information
// return: 'true' on success
// 'false' on failure
-bool
-ProcessGDBRemote::GetGDBServerRegisterInfo (ArchSpec &arch_to_use)
-{
- // Make sure LLDB has an XML parser it can use first
- if (!XMLDocument::XMLEnabled())
- return false;
-
- // redirect libxml2's error handler since the default prints to stdout
-
- GDBRemoteCommunicationClient & comm = m_gdb_comm;
-
- // check that we have extended feature read support
- if ( !comm.GetQXferFeaturesReadSupported( ) )
- return false;
-
- // request the target xml file
- std::string raw;
- lldb_private::Error lldberr;
- if (!comm.ReadExtFeature(ConstString("features"),
- ConstString("target.xml"),
- raw,
- lldberr))
- {
- return false;
- }
+bool ProcessGDBRemote::GetGDBServerRegisterInfo(ArchSpec &arch_to_use) {
+ // Make sure LLDB has an XML parser it can use first
+ if (!XMLDocument::XMLEnabled())
+ return false;
+ // redirect libxml2's error handler since the default prints to stdout
- XMLDocument xml_document;
+ GDBRemoteCommunicationClient &comm = m_gdb_comm;
- if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml"))
- {
- GdbServerTargetInfo target_info;
+ // check that we have extended feature read support
+ if (!comm.GetQXferFeaturesReadSupported())
+ return false;
- XMLNode target_node = xml_document.GetRootElement("target");
- if (target_node)
- {
- XMLNode feature_node;
- target_node.ForEachChildElement([&target_info, this, &feature_node](const XMLNode &node) -> bool
- {
- llvm::StringRef name = node.GetName();
- if (name == "architecture")
- {
- node.GetElementText(target_info.arch);
- }
- else if (name == "osabi")
- {
- node.GetElementText(target_info.osabi);
- }
- else if (name == "xi:include" || name == "include")
- {
- llvm::StringRef href = node.GetAttributeValue("href");
- if (!href.empty())
- target_info.includes.push_back(href.str());
- }
- else if (name == "feature")
- {
- feature_node = node;
- }
- else if (name == "groups")
- {
- node.ForEachChildElementWithName("group", [&target_info](const XMLNode &node) -> bool {
- uint32_t set_id = UINT32_MAX;
- RegisterSetInfo set_info;
-
- node.ForEachAttribute([&set_id, &set_info](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
- if (name == "id")
- set_id = StringConvert::ToUInt32(value.data(), UINT32_MAX, 0);
- if (name == "name")
- set_info.name = ConstString(value);
- return true; // Keep iterating through all attributes
- });
-
- if (set_id != UINT32_MAX)
- target_info.reg_set_map[set_id] = set_info;
- return true; // Keep iterating through all "group" elements
+ // request the target xml file
+ std::string raw;
+ lldb_private::Error lldberr;
+ if (!comm.ReadExtFeature(ConstString("features"), ConstString("target.xml"),
+ raw, lldberr)) {
+ return false;
+ }
+
+ XMLDocument xml_document;
+
+ if (xml_document.ParseMemory(raw.c_str(), raw.size(), "target.xml")) {
+ GdbServerTargetInfo target_info;
+
+ XMLNode target_node = xml_document.GetRootElement("target");
+ if (target_node) {
+ XMLNode feature_node;
+ target_node.ForEachChildElement([&target_info, this, &feature_node](
+ const XMLNode &node) -> bool {
+ llvm::StringRef name = node.GetName();
+ if (name == "architecture") {
+ node.GetElementText(target_info.arch);
+ } else if (name == "osabi") {
+ node.GetElementText(target_info.osabi);
+ } else if (name == "xi:include" || name == "include") {
+ llvm::StringRef href = node.GetAttributeValue("href");
+ if (!href.empty())
+ target_info.includes.push_back(href.str());
+ } else if (name == "feature") {
+ feature_node = node;
+ } else if (name == "groups") {
+ node.ForEachChildElementWithName(
+ "group", [&target_info](const XMLNode &node) -> bool {
+ uint32_t set_id = UINT32_MAX;
+ RegisterSetInfo set_info;
+
+ node.ForEachAttribute(
+ [&set_id, &set_info](const llvm::StringRef &name,
+ const llvm::StringRef &value) -> bool {
+ if (name == "id")
+ set_id = StringConvert::ToUInt32(value.data(),
+ UINT32_MAX, 0);
+ if (name == "name")
+ set_info.name = ConstString(value);
+ return true; // Keep iterating through all attributes
});
- }
- return true; // Keep iterating through all children of the target_node
- });
-
- // Initialize these outside of ParseRegisters, since they should not be reset inside each include feature
- uint32_t cur_reg_num = 0;
- uint32_t reg_offset = 0;
-
- // Don't use Process::GetABI, this code gets called from DidAttach, and in that context we haven't
- // set the Target's architecture yet, so the ABI is also potentially incorrect.
- ABISP abi_to_use_sp = ABI::FindPlugin(arch_to_use);
- if (feature_node)
- {
- ParseRegisters(feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset);
- }
- for (const auto &include : target_info.includes)
- {
- // request register file
- std::string xml_data;
- if (!comm.ReadExtFeature(ConstString("features"),
- ConstString(include),
- xml_data,
- lldberr))
- continue;
-
- XMLDocument include_xml_document;
- include_xml_document.ParseMemory(xml_data.data(), xml_data.size(), include.c_str());
- XMLNode include_feature_node = include_xml_document.GetRootElement("feature");
- if (include_feature_node)
- {
- ParseRegisters(include_feature_node, target_info, this->m_register_info, abi_to_use_sp, cur_reg_num, reg_offset);
- }
- }
- this->m_register_info.Finalize(arch_to_use);
+ if (set_id != UINT32_MAX)
+ target_info.reg_set_map[set_id] = set_info;
+ return true; // Keep iterating through all "group" elements
+ });
+ }
+ return true; // Keep iterating through all children of the target_node
+ });
+
+ // Initialize these outside of ParseRegisters, since they should not be
+ // reset inside each include feature
+ uint32_t cur_reg_num = 0;
+ uint32_t reg_offset = 0;
+
+ // Don't use Process::GetABI, this code gets called from DidAttach, and in
+ // that context we haven't
+ // set the Target's architecture yet, so the ABI is also potentially
+ // incorrect.
+ ABISP abi_to_use_sp = ABI::FindPlugin(arch_to_use);
+ if (feature_node) {
+ ParseRegisters(feature_node, target_info, this->m_register_info,
+ abi_to_use_sp, cur_reg_num, reg_offset);
+ }
+
+ for (const auto &include : target_info.includes) {
+ // request register file
+ std::string xml_data;
+ if (!comm.ReadExtFeature(ConstString("features"), ConstString(include),
+ xml_data, lldberr))
+ continue;
+
+ XMLDocument include_xml_document;
+ include_xml_document.ParseMemory(xml_data.data(), xml_data.size(),
+ include.c_str());
+ XMLNode include_feature_node =
+ include_xml_document.GetRootElement("feature");
+ if (include_feature_node) {
+ ParseRegisters(include_feature_node, target_info,
+ this->m_register_info, abi_to_use_sp, cur_reg_num,
+ reg_offset);
}
+ }
+ this->m_register_info.Finalize(arch_to_use);
}
+ }
- return m_register_info.GetNumRegisters() > 0;
+ return m_register_info.GetNumRegisters() > 0;
}
-Error
-ProcessGDBRemote::GetLoadedModuleList (LoadedModuleInfoList & list)
-{
- // Make sure LLDB has an XML parser it can use first
- if (!XMLDocument::XMLEnabled())
- return Error (0, ErrorType::eErrorTypeGeneric);
+Error ProcessGDBRemote::GetLoadedModuleList(LoadedModuleInfoList &list) {
+ // Make sure LLDB has an XML parser it can use first
+ if (!XMLDocument::XMLEnabled())
+ return Error(0, ErrorType::eErrorTypeGeneric);
- Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS);
- if (log)
- log->Printf ("ProcessGDBRemote::%s", __FUNCTION__);
+ Log *log = GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS);
+ if (log)
+ log->Printf("ProcessGDBRemote::%s", __FUNCTION__);
- GDBRemoteCommunicationClient & comm = m_gdb_comm;
+ GDBRemoteCommunicationClient &comm = m_gdb_comm;
- // check that we have extended feature read support
- if (comm.GetQXferLibrariesSVR4ReadSupported ()) {
- list.clear ();
+ // check that we have extended feature read support
+ if (comm.GetQXferLibrariesSVR4ReadSupported()) {
+ list.clear();
- // request the loaded library list
- std::string raw;
- lldb_private::Error lldberr;
+ // request the loaded library list
+ std::string raw;
+ lldb_private::Error lldberr;
- if (!comm.ReadExtFeature (ConstString ("libraries-svr4"), ConstString (""), raw, lldberr))
- return Error (0, ErrorType::eErrorTypeGeneric);
+ if (!comm.ReadExtFeature(ConstString("libraries-svr4"), ConstString(""),
+ raw, lldberr))
+ return Error(0, ErrorType::eErrorTypeGeneric);
- // parse the xml file in memory
- if (log)
- log->Printf ("parsing: %s", raw.c_str());
- XMLDocument doc;
+ // parse the xml file in memory
+ if (log)
+ log->Printf("parsing: %s", raw.c_str());
+ XMLDocument doc;
- if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
- return Error (0, ErrorType::eErrorTypeGeneric);
+ if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
+ return Error(0, ErrorType::eErrorTypeGeneric);
- XMLNode root_element = doc.GetRootElement("library-list-svr4");
- if (!root_element)
- return Error();
+ XMLNode root_element = doc.GetRootElement("library-list-svr4");
+ if (!root_element)
+ return Error();
- // main link map structure
- llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm");
- if (!main_lm.empty())
- {
- list.m_link_map = StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0);
- }
+ // main link map structure
+ llvm::StringRef main_lm = root_element.GetAttributeValue("main-lm");
+ if (!main_lm.empty()) {
+ list.m_link_map =
+ StringConvert::ToUInt64(main_lm.data(), LLDB_INVALID_ADDRESS, 0);
+ }
- root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
+ root_element.ForEachChildElementWithName(
+ "library", [log, &list](const XMLNode &library) -> bool {
- LoadedModuleInfoList::LoadedModuleInfo module;
+ LoadedModuleInfoList::LoadedModuleInfo module;
- library.ForEachAttribute([log, &module](const llvm::StringRef &name, const llvm::StringRef &value) -> bool {
+ library.ForEachAttribute(
+ [log, &module](const llvm::StringRef &name,
+ const llvm::StringRef &value) -> bool {
if (name == "name")
- module.set_name (value.str());
- else if (name == "lm")
- {
- // the address of the link_map struct.
- module.set_link_map(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
- }
- else if (name == "l_addr")
- {
- // the displacement as read from the field 'l_addr' of the link_map struct.
- module.set_base(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
- // base address is always a displacement, not an absolute value.
- module.set_base_is_offset(true);
- }
- else if (name == "l_ld")
- {
- // the memory address of the libraries PT_DYAMIC section.
- module.set_dynamic(StringConvert::ToUInt64(value.data(), LLDB_INVALID_ADDRESS, 0));
+ module.set_name(value.str());
+ else if (name == "lm") {
+ // the address of the link_map struct.
+ module.set_link_map(StringConvert::ToUInt64(
+ value.data(), LLDB_INVALID_ADDRESS, 0));
+ } else if (name == "l_addr") {
+ // the displacement as read from the field 'l_addr' of the
+ // link_map struct.
+ module.set_base(StringConvert::ToUInt64(
+ value.data(), LLDB_INVALID_ADDRESS, 0));
+ // base address is always a displacement, not an absolute
+ // value.
+ module.set_base_is_offset(true);
+ } else if (name == "l_ld") {
+ // the memory address of the libraries PT_DYAMIC section.
+ module.set_dynamic(StringConvert::ToUInt64(
+ value.data(), LLDB_INVALID_ADDRESS, 0));
}
return true; // Keep iterating over all properties of "library"
- });
-
- if (log)
- {
- std::string name;
- lldb::addr_t lm=0, base=0, ld=0;
- bool base_is_offset;
-
- module.get_name (name);
- module.get_link_map (lm);
- module.get_base (base);
- module.get_base_is_offset (base_is_offset);
- module.get_dynamic (ld);
-
- log->Printf ("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64 "[%s], ld:0x%08" PRIx64 ", name:'%s')", lm, base, (base_is_offset ? "offset" : "absolute"), ld, name.c_str());
- }
-
- list.add (module);
- return true; // Keep iterating over all "library" elements in the root node
+ });
+
+ if (log) {
+ std::string name;
+ lldb::addr_t lm = 0, base = 0, ld = 0;
+ bool base_is_offset;
+
+ module.get_name(name);
+ module.get_link_map(lm);
+ module.get_base(base);
+ module.get_base_is_offset(base_is_offset);
+ module.get_dynamic(ld);
+
+ log->Printf("found (link_map:0x%08" PRIx64 ", base:0x%08" PRIx64
+ "[%s], ld:0x%08" PRIx64 ", name:'%s')",
+ lm, base, (base_is_offset ? "offset" : "absolute"), ld,
+ name.c_str());
+ }
+
+ list.add(module);
+ return true; // Keep iterating over all "library" elements in the root
+ // node
});
- if (log)
- log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size());
- } else if (comm.GetQXferLibrariesReadSupported ()) {
- list.clear ();
-
- // request the loaded library list
- std::string raw;
- lldb_private::Error lldberr;
-
- if (!comm.ReadExtFeature (ConstString ("libraries"), ConstString (""), raw, lldberr))
- return Error (0, ErrorType::eErrorTypeGeneric);
-
- if (log)
- log->Printf ("parsing: %s", raw.c_str());
- XMLDocument doc;
-
- if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
- return Error (0, ErrorType::eErrorTypeGeneric);
-
- XMLNode root_element = doc.GetRootElement("library-list");
- if (!root_element)
- return Error();
-
- root_element.ForEachChildElementWithName("library", [log, &list](const XMLNode &library) -> bool {
- LoadedModuleInfoList::LoadedModuleInfo module;
-
- llvm::StringRef name = library.GetAttributeValue("name");
- module.set_name(name.str());
+ if (log)
+ log->Printf("found %" PRId32 " modules in total",
+ (int)list.m_list.size());
+ } else if (comm.GetQXferLibrariesReadSupported()) {
+ list.clear();
- // The base address of a given library will be the address of its
- // first section. Most remotes send only one section for Windows
- // targets for example.
- const XMLNode &section = library.FindFirstChildElementWithName("section");
- llvm::StringRef address = section.GetAttributeValue("address");
- module.set_base(StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0));
- // These addresses are absolute values.
- module.set_base_is_offset(false);
+ // request the loaded library list
+ std::string raw;
+ lldb_private::Error lldberr;
- if (log)
- {
- std::string name;
- lldb::addr_t base = 0;
- bool base_is_offset;
- module.get_name (name);
- module.get_base (base);
- module.get_base_is_offset (base_is_offset);
-
- log->Printf ("found (base:0x%08" PRIx64 "[%s], name:'%s')", base, (base_is_offset ? "offset" : "absolute"), name.c_str());
- }
+ if (!comm.ReadExtFeature(ConstString("libraries"), ConstString(""), raw,
+ lldberr))
+ return Error(0, ErrorType::eErrorTypeGeneric);
- list.add (module);
- return true; // Keep iterating over all "library" elements in the root node
+ if (log)
+ log->Printf("parsing: %s", raw.c_str());
+ XMLDocument doc;
+
+ if (!doc.ParseMemory(raw.c_str(), raw.size(), "noname.xml"))
+ return Error(0, ErrorType::eErrorTypeGeneric);
+
+ XMLNode root_element = doc.GetRootElement("library-list");
+ if (!root_element)
+ return Error();
+
+ root_element.ForEachChildElementWithName(
+ "library", [log, &list](const XMLNode &library) -> bool {
+ LoadedModuleInfoList::LoadedModuleInfo module;
+
+ llvm::StringRef name = library.GetAttributeValue("name");
+ module.set_name(name.str());
+
+ // The base address of a given library will be the address of its
+ // first section. Most remotes send only one section for Windows
+ // targets for example.
+ const XMLNode &section =
+ library.FindFirstChildElementWithName("section");
+ llvm::StringRef address = section.GetAttributeValue("address");
+ module.set_base(
+ StringConvert::ToUInt64(address.data(), LLDB_INVALID_ADDRESS, 0));
+ // These addresses are absolute values.
+ module.set_base_is_offset(false);
+
+ if (log) {
+ std::string name;
+ lldb::addr_t base = 0;
+ bool base_is_offset;
+ module.get_name(name);
+ module.get_base(base);
+ module.get_base_is_offset(base_is_offset);
+
+ log->Printf("found (base:0x%08" PRIx64 "[%s], name:'%s')", base,
+ (base_is_offset ? "offset" : "absolute"), name.c_str());
+ }
+
+ list.add(module);
+ return true; // Keep iterating over all "library" elements in the root
+ // node
});
- if (log)
- log->Printf ("found %" PRId32 " modules in total", (int) list.m_list.size());
- } else {
- return Error (0, ErrorType::eErrorTypeGeneric);
- }
+ if (log)
+ log->Printf("found %" PRId32 " modules in total",
+ (int)list.m_list.size());
+ } else {
+ return Error(0, ErrorType::eErrorTypeGeneric);
+ }
- return Error();
+ return Error();
}
-lldb::ModuleSP
-ProcessGDBRemote::LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map,
- lldb::addr_t base_addr, bool value_is_offset)
-{
- DynamicLoader *loader = GetDynamicLoader();
- if (!loader)
- return nullptr;
+lldb::ModuleSP ProcessGDBRemote::LoadModuleAtAddress(const FileSpec &file,
+ lldb::addr_t link_map,
+ lldb::addr_t base_addr,
+ bool value_is_offset) {
+ DynamicLoader *loader = GetDynamicLoader();
+ if (!loader)
+ return nullptr;
- return loader->LoadModuleAtAddress(file, link_map, base_addr, value_is_offset);
+ return loader->LoadModuleAtAddress(file, link_map, base_addr,
+ value_is_offset);
}
-size_t
-ProcessGDBRemote::LoadModules (LoadedModuleInfoList &module_list)
-{
- using lldb_private::process_gdb_remote::ProcessGDBRemote;
-
- // request a list of loaded libraries from GDBServer
- if (GetLoadedModuleList (module_list).Fail())
- return 0;
+size_t ProcessGDBRemote::LoadModules(LoadedModuleInfoList &module_list) {
+ using lldb_private::process_gdb_remote::ProcessGDBRemote;
- // get a list of all the modules
- ModuleList new_modules;
+ // request a list of loaded libraries from GDBServer
+ if (GetLoadedModuleList(module_list).Fail())
+ return 0;
- for (LoadedModuleInfoList::LoadedModuleInfo & modInfo : module_list.m_list)
- {
- std::string mod_name;
- lldb::addr_t mod_base;
- lldb::addr_t link_map;
- bool mod_base_is_offset;
-
- bool valid = true;
- valid &= modInfo.get_name (mod_name);
- valid &= modInfo.get_base (mod_base);
- valid &= modInfo.get_base_is_offset (mod_base_is_offset);
- if (!valid)
- continue;
-
- if (!modInfo.get_link_map (link_map))
- link_map = LLDB_INVALID_ADDRESS;
-
- FileSpec file (mod_name.c_str(), true);
- lldb::ModuleSP module_sp = LoadModuleAtAddress (file, link_map, mod_base,
- mod_base_is_offset);
-
- if (module_sp.get())
- new_modules.Append (module_sp);
- }
+ // get a list of all the modules
+ ModuleList new_modules;
+
+ for (LoadedModuleInfoList::LoadedModuleInfo &modInfo : module_list.m_list) {
+ std::string mod_name;
+ lldb::addr_t mod_base;
+ lldb::addr_t link_map;
+ bool mod_base_is_offset;
+
+ bool valid = true;
+ valid &= modInfo.get_name(mod_name);
+ valid &= modInfo.get_base(mod_base);
+ valid &= modInfo.get_base_is_offset(mod_base_is_offset);
+ if (!valid)
+ continue;
+
+ if (!modInfo.get_link_map(link_map))
+ link_map = LLDB_INVALID_ADDRESS;
+
+ FileSpec file(mod_name, true);
+ lldb::ModuleSP module_sp =
+ LoadModuleAtAddress(file, link_map, mod_base, mod_base_is_offset);
+
+ if (module_sp.get())
+ new_modules.Append(module_sp);
+ }
+
+ if (new_modules.GetSize() > 0) {
+ ModuleList removed_modules;
+ Target &target = GetTarget();
+ ModuleList &loaded_modules = m_process->GetTarget().GetImages();
+
+ for (size_t i = 0; i < loaded_modules.GetSize(); ++i) {
+ const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i);
+
+ bool found = false;
+ for (size_t j = 0; j < new_modules.GetSize(); ++j) {
+ if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get())
+ found = true;
+ }
+
+ // The main executable will never be included in libraries-svr4, don't
+ // remove it
+ if (!found &&
+ loaded_module.get() != target.GetExecutableModulePointer()) {
+ removed_modules.Append(loaded_module);
+ }
+ }
+
+ loaded_modules.Remove(removed_modules);
+ m_process->GetTarget().ModulesDidUnload(removed_modules, false);
+
+ new_modules.ForEach([&target](const lldb::ModuleSP module_sp) -> bool {
+ lldb_private::ObjectFile *obj = module_sp->GetObjectFile();
+ if (!obj)
+ return true;
- if (new_modules.GetSize() > 0)
- {
- ModuleList removed_modules;
- Target &target = GetTarget();
- ModuleList &loaded_modules = m_process->GetTarget().GetImages();
+ if (obj->GetType() != ObjectFile::Type::eTypeExecutable)
+ return true;
- for (size_t i = 0; i < loaded_modules.GetSize(); ++i)
- {
- const lldb::ModuleSP loaded_module = loaded_modules.GetModuleAtIndex(i);
+ lldb::ModuleSP module_copy_sp = module_sp;
+ target.SetExecutableModule(module_copy_sp, false);
+ return false;
+ });
- bool found = false;
- for (size_t j = 0; j < new_modules.GetSize(); ++j)
- {
- if (new_modules.GetModuleAtIndex(j).get() == loaded_module.get())
- found = true;
- }
+ loaded_modules.AppendIfNeeded(new_modules);
+ m_process->GetTarget().ModulesDidLoad(new_modules);
+ }
- // The main executable will never be included in libraries-svr4, don't remove it
- if (!found && loaded_module.get() != target.GetExecutableModulePointer())
- {
- removed_modules.Append (loaded_module);
- }
- }
-
- loaded_modules.Remove (removed_modules);
- m_process->GetTarget().ModulesDidUnload (removed_modules, false);
+ return new_modules.GetSize();
+}
- new_modules.ForEach ([&target](const lldb::ModuleSP module_sp) -> bool
- {
- lldb_private::ObjectFile * obj = module_sp->GetObjectFile ();
- if (!obj)
- return true;
+size_t ProcessGDBRemote::LoadModules() {
+ LoadedModuleInfoList module_list;
+ return LoadModules(module_list);
+}
- if (obj->GetType () != ObjectFile::Type::eTypeExecutable)
- return true;
+Error ProcessGDBRemote::GetFileLoadAddress(const FileSpec &file,
+ bool &is_loaded,
+ lldb::addr_t &load_addr) {
+ is_loaded = false;
+ load_addr = LLDB_INVALID_ADDRESS;
+
+ std::string file_path = file.GetPath(false);
+ if (file_path.empty())
+ return Error("Empty file name specified");
+
+ StreamString packet;
+ packet.PutCString("qFileLoadAddress:");
+ packet.PutCStringAsRawHex8(file_path.c_str());
+
+ StringExtractorGDBRemote response;
+ if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString(), response,
+ false) !=
+ GDBRemoteCommunication::PacketResult::Success)
+ return Error("Sending qFileLoadAddress packet failed");
+
+ if (response.IsErrorResponse()) {
+ if (response.GetError() == 1) {
+ // The file is not loaded into the inferior
+ is_loaded = false;
+ load_addr = LLDB_INVALID_ADDRESS;
+ return Error();
+ }
+
+ return Error(
+ "Fetching file load address from remote server returned an error");
+ }
+
+ if (response.IsNormalResponse()) {
+ is_loaded = true;
+ load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
+ return Error();
+ }
- lldb::ModuleSP module_copy_sp = module_sp;
- target.SetExecutableModule (module_copy_sp, false);
- return false;
- });
+ return Error("Unknown error happened during sending the load address packet");
+}
- loaded_modules.AppendIfNeeded (new_modules);
- m_process->GetTarget().ModulesDidLoad (new_modules);
- }
+void ProcessGDBRemote::ModulesDidLoad(ModuleList &module_list) {
+ // We must call the lldb_private::Process::ModulesDidLoad () first before we
+ // do anything
+ Process::ModulesDidLoad(module_list);
- return new_modules.GetSize();
+ // After loading shared libraries, we can ask our remote GDB server if
+ // it needs any symbols.
+ m_gdb_comm.ServeSymbolLookups(this);
}
-size_t
-ProcessGDBRemote::LoadModules ()
-{
- LoadedModuleInfoList module_list;
- return LoadModules (module_list);
+void ProcessGDBRemote::HandleAsyncStdout(llvm::StringRef out) {
+ AppendSTDOUT(out.data(), out.size());
}
-Error
-ProcessGDBRemote::GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr)
-{
- is_loaded = false;
- load_addr = LLDB_INVALID_ADDRESS;
-
- std::string file_path = file.GetPath(false);
- if (file_path.empty ())
- return Error("Empty file name specified");
-
- StreamString packet;
- packet.PutCString("qFileLoadAddress:");
- packet.PutCStringAsRawHex8(file_path.c_str());
-
- StringExtractorGDBRemote response;
- if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(), response, false) != GDBRemoteCommunication::PacketResult::Success)
- return Error("Sending qFileLoadAddress packet failed");
+static const char *end_delimiter = "--end--;";
+static const int end_delimiter_len = 8;
+
+void ProcessGDBRemote::HandleAsyncMisc(llvm::StringRef data) {
+ std::string input = data.str(); // '1' to move beyond 'A'
+ if (m_partial_profile_data.length() > 0) {
+ m_partial_profile_data.append(input);
+ input = m_partial_profile_data;
+ m_partial_profile_data.clear();
+ }
+
+ size_t found, pos = 0, len = input.length();
+ while ((found = input.find(end_delimiter, pos)) != std::string::npos) {
+ StringExtractorGDBRemote profileDataExtractor(
+ input.substr(pos, found).c_str());
+ std::string profile_data =
+ HarmonizeThreadIdsForProfileData(profileDataExtractor);
+ BroadcastAsyncProfileData(profile_data);
+
+ pos = found + end_delimiter_len;
+ }
+
+ if (pos < len) {
+ // Last incomplete chunk.
+ m_partial_profile_data = input.substr(pos);
+ }
+}
- if (response.IsErrorResponse())
- {
- if (response.GetError() == 1)
- {
- // The file is not loaded into the inferior
- is_loaded = false;
- load_addr = LLDB_INVALID_ADDRESS;
- return Error();
+std::string ProcessGDBRemote::HarmonizeThreadIdsForProfileData(
+ StringExtractorGDBRemote &profileDataExtractor) {
+ std::map<uint64_t, uint32_t> new_thread_id_to_used_usec_map;
+ std::string output;
+ llvm::raw_string_ostream output_stream(output);
+ llvm::StringRef name, value;
+
+ // Going to assuming thread_used_usec comes first, else bail out.
+ while (profileDataExtractor.GetNameColonValue(name, value)) {
+ if (name.compare("thread_used_id") == 0) {
+ StringExtractor threadIDHexExtractor(value);
+ uint64_t thread_id = threadIDHexExtractor.GetHexMaxU64(false, 0);
+
+ bool has_used_usec = false;
+ uint32_t curr_used_usec = 0;
+ llvm::StringRef usec_name, usec_value;
+ uint32_t input_file_pos = profileDataExtractor.GetFilePos();
+ if (profileDataExtractor.GetNameColonValue(usec_name, usec_value)) {
+ if (usec_name.equals("thread_used_usec")) {
+ has_used_usec = true;
+ usec_value.getAsInteger(0, curr_used_usec);
+ } else {
+ // We didn't find what we want, it is probably
+ // an older version. Bail out.
+ profileDataExtractor.SetFilePos(input_file_pos);
+ }
+ }
+
+ if (has_used_usec) {
+ uint32_t prev_used_usec = 0;
+ std::map<uint64_t, uint32_t>::iterator iterator =
+ m_thread_id_to_used_usec_map.find(thread_id);
+ if (iterator != m_thread_id_to_used_usec_map.end()) {
+ prev_used_usec = m_thread_id_to_used_usec_map[thread_id];
}
- return Error("Fetching file load address from remote server returned an error");
- }
+ uint32_t real_used_usec = curr_used_usec - prev_used_usec;
+ // A good first time record is one that runs for at least 0.25 sec
+ bool good_first_time =
+ (prev_used_usec == 0) && (real_used_usec > 250000);
+ bool good_subsequent_time =
+ (prev_used_usec > 0) &&
+ ((real_used_usec > 0) || (HasAssignedIndexIDToThread(thread_id)));
+
+ if (good_first_time || good_subsequent_time) {
+ // We try to avoid doing too many index id reservation,
+ // resulting in fast increase of index ids.
+
+ output_stream << name << ":";
+ int32_t index_id = AssignIndexIDToThread(thread_id);
+ output_stream << index_id << ";";
+
+ output_stream << usec_name << ":" << usec_value << ";";
+ } else {
+ // Skip past 'thread_used_name'.
+ llvm::StringRef local_name, local_value;
+ profileDataExtractor.GetNameColonValue(local_name, local_value);
+ }
- if (response.IsNormalResponse())
- {
- is_loaded = true;
- load_addr = response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS);
- return Error();
+ // Store current time as previous time so that they can be compared
+ // later.
+ new_thread_id_to_used_usec_map[thread_id] = curr_used_usec;
+ } else {
+ // Bail out and use old string.
+ output_stream << name << ":" << value << ";";
+ }
+ } else {
+ output_stream << name << ":" << value << ";";
}
+ }
+ output_stream << end_delimiter;
+ m_thread_id_to_used_usec_map = new_thread_id_to_used_usec_map;
- return Error("Unknown error happened during sending the load address packet");
+ return output_stream.str();
}
+void ProcessGDBRemote::HandleStopReply() {
+ if (GetStopID() != 0)
+ return;
-void
-ProcessGDBRemote::ModulesDidLoad (ModuleList &module_list)
-{
- // We must call the lldb_private::Process::ModulesDidLoad () first before we do anything
- Process::ModulesDidLoad (module_list);
-
- // After loading shared libraries, we can ask our remote GDB server if
- // it needs any symbols.
- m_gdb_comm.ServeSymbolLookups(this);
+ if (GetID() == LLDB_INVALID_PROCESS_ID) {
+ lldb::pid_t pid = m_gdb_comm.GetCurrentProcessID();
+ if (pid != LLDB_INVALID_PROCESS_ID)
+ SetID(pid);
+ }
+ BuildDynamicRegisterInfo(true);
}
-
-class CommandObjectProcessGDBRemoteSpeedTest: public CommandObjectParsed
-{
-public:
- CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "process plugin packet speed-test",
- "Tests packet speeds of various sizes to determine the performance characteristics of the GDB remote connection. ",
- NULL),
- m_option_group (interpreter),
- m_num_packets (LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount, "The number of packets to send of each varying size (default is 1000).", 1000),
- m_max_send (LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount, "The maximum number of bytes to send in a packet. Sizes increase in powers of 2 while the size is less than or equal to this option value. (default 1024).", 1024),
- m_max_recv (LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount, "The maximum number of bytes to receive in a packet. Sizes increase in powers of 2 while the size is less than or equal to this option value. (default 1024).", 1024),
- m_json (LLDB_OPT_SET_1, false, "json", 'j', "Print the output as JSON data for easy parsing.", false, true)
- {
- m_option_group.Append (&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Append (&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Append (&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Append (&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
- m_option_group.Finalize();
- }
-
- ~CommandObjectProcessGDBRemoteSpeedTest ()
- {
+static const char *const s_async_json_packet_prefix = "JSON-async:";
+
+static StructuredData::ObjectSP
+ParseStructuredDataPacket(llvm::StringRef packet) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+
+ if (!packet.consume_front(s_async_json_packet_prefix)) {
+ if (log) {
+ log->Printf(
+ "GDBRemoteCommmunicationClientBase::%s() received $J packet "
+ "but was not a StructuredData packet: packet starts with "
+ "%s",
+ __FUNCTION__,
+ packet.slice(0, strlen(s_async_json_packet_prefix)).str().c_str());
+ }
+ return StructuredData::ObjectSP();
+ }
+
+ // This is an asynchronous JSON packet, destined for a
+ // StructuredDataPlugin.
+ StructuredData::ObjectSP json_sp = StructuredData::ParseJSON(packet);
+ if (log) {
+ if (json_sp) {
+ StreamString json_str;
+ json_sp->Dump(json_str);
+ json_str.Flush();
+ log->Printf("ProcessGDBRemote::%s() "
+ "received Async StructuredData packet: %s",
+ __FUNCTION__, json_str.GetData());
+ } else {
+ log->Printf("ProcessGDBRemote::%s"
+ "() received StructuredData packet:"
+ " parse failure",
+ __FUNCTION__);
}
+ }
+ return json_sp;
+}
+void ProcessGDBRemote::HandleAsyncStructuredDataPacket(llvm::StringRef data) {
+ auto structured_data_sp = ParseStructuredDataPacket(data);
+ if (structured_data_sp)
+ RouteAsyncStructuredData(structured_data_sp);
+}
- Options *
- GetOptions () override
- {
- return &m_option_group;
+class CommandObjectProcessGDBRemoteSpeedTest : public CommandObjectParsed {
+public:
+ CommandObjectProcessGDBRemoteSpeedTest(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process plugin packet speed-test",
+ "Tests packet speeds of various sizes to determine "
+ "the performance characteristics of the GDB remote "
+ "connection. ",
+ NULL),
+ m_option_group(),
+ m_num_packets(LLDB_OPT_SET_1, false, "count", 'c', 0, eArgTypeCount,
+ "The number of packets to send of each varying size "
+ "(default is 1000).",
+ 1000),
+ m_max_send(LLDB_OPT_SET_1, false, "max-send", 's', 0, eArgTypeCount,
+ "The maximum number of bytes to send in a packet. Sizes "
+ "increase in powers of 2 while the size is less than or "
+ "equal to this option value. (default 1024).",
+ 1024),
+ m_max_recv(LLDB_OPT_SET_1, false, "max-receive", 'r', 0, eArgTypeCount,
+ "The maximum number of bytes to receive in a packet. Sizes "
+ "increase in powers of 2 while the size is less than or "
+ "equal to this option value. (default 1024).",
+ 1024),
+ m_json(LLDB_OPT_SET_1, false, "json", 'j',
+ "Print the output as JSON data for easy parsing.", false, true) {
+ m_option_group.Append(&m_num_packets, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Append(&m_max_send, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Append(&m_max_recv, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Append(&m_json, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
+ m_option_group.Finalize();
+ }
+
+ ~CommandObjectProcessGDBRemoteSpeedTest() {}
+
+ Options *GetOptions() override { return &m_option_group; }
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext()
+ .GetProcessPtr();
+ if (process) {
+ StreamSP output_stream_sp(
+ m_interpreter.GetDebugger().GetAsyncOutputStream());
+ result.SetImmediateOutputStream(output_stream_sp);
+
+ const uint32_t num_packets =
+ (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue();
+ const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue();
+ const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue();
+ const bool json = m_json.GetOptionValue().GetCurrentValue();
+ const uint64_t k_recv_amount =
+ 4 * 1024 * 1024; // Receive amount in bytes
+ process->GetGDBRemote().TestPacketSpeed(
+ num_packets, max_send, max_recv, k_recv_amount, json,
+ output_stream_sp ? *output_stream_sp : result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ } else {
+ result.AppendErrorWithFormat("'%s' takes no arguments",
+ m_cmd_name.c_str());
}
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
- bool
- DoExecute (Args& command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc == 0)
- {
- ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process)
- {
- StreamSP output_stream_sp (m_interpreter.GetDebugger().GetAsyncOutputStream());
- result.SetImmediateOutputStream (output_stream_sp);
-
- const uint32_t num_packets = (uint32_t)m_num_packets.GetOptionValue().GetCurrentValue();
- const uint64_t max_send = m_max_send.GetOptionValue().GetCurrentValue();
- const uint64_t max_recv = m_max_recv.GetOptionValue().GetCurrentValue();
- const bool json = m_json.GetOptionValue().GetCurrentValue();
- if (output_stream_sp)
- process->GetGDBRemote().TestPacketSpeed (num_packets, max_send, max_recv, json, *output_stream_sp);
- else
- {
- process->GetGDBRemote().TestPacketSpeed (num_packets, max_send, max_recv, json, result.GetOutputStream());
- }
- result.SetStatus (eReturnStatusSuccessFinishResult);
- return true;
- }
- }
- else
- {
- result.AppendErrorWithFormat ("'%s' takes no arguments", m_cmd_name.c_str());
- }
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
protected:
- OptionGroupOptions m_option_group;
- OptionGroupUInt64 m_num_packets;
- OptionGroupUInt64 m_max_send;
- OptionGroupUInt64 m_max_recv;
- OptionGroupBoolean m_json;
-
+ OptionGroupOptions m_option_group;
+ OptionGroupUInt64 m_num_packets;
+ OptionGroupUInt64 m_max_send;
+ OptionGroupUInt64 m_max_recv;
+ OptionGroupBoolean m_json;
};
-class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed
-{
+class CommandObjectProcessGDBRemotePacketHistory : public CommandObjectParsed {
private:
-
public:
- CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "process plugin packet history",
- "Dumps the packet history buffer. ",
- NULL)
- {
- }
-
- ~CommandObjectProcessGDBRemotePacketHistory ()
- {
- }
-
- bool
- DoExecute (Args& command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc == 0)
- {
- ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process)
- {
- process->GetGDBRemote().DumpHistory(result.GetOutputStream());
- result.SetStatus (eReturnStatusSuccessFinishResult);
- return true;
- }
- }
- else
- {
- result.AppendErrorWithFormat ("'%s' takes no arguments", m_cmd_name.c_str());
- }
- result.SetStatus (eReturnStatusFailed);
- return false;
+ CommandObjectProcessGDBRemotePacketHistory(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process plugin packet history",
+ "Dumps the packet history buffer. ", NULL) {}
+
+ ~CommandObjectProcessGDBRemotePacketHistory() {}
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext()
+ .GetProcessPtr();
+ if (process) {
+ process->GetGDBRemote().DumpHistory(result.GetOutputStream());
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
+ } else {
+ result.AppendErrorWithFormat("'%s' takes no arguments",
+ m_cmd_name.c_str());
}
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
};
-class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed
-{
+class CommandObjectProcessGDBRemotePacketXferSize : public CommandObjectParsed {
private:
-
public:
- CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "process plugin packet xfer-size",
- "Maximum size that lldb will try to read/write one one chunk.",
- NULL)
- {
- }
-
- ~CommandObjectProcessGDBRemotePacketXferSize ()
- {
- }
-
- bool
- DoExecute (Args& command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc == 0)
- {
- result.AppendErrorWithFormat ("'%s' takes an argument to specify the max amount to be transferred when reading/writing", m_cmd_name.c_str());
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process)
- {
- const char *packet_size = command.GetArgumentAtIndex(0);
- errno = 0;
- uint64_t user_specified_max = strtoul (packet_size, NULL, 10);
- if (errno == 0 && user_specified_max != 0)
- {
- process->SetUserSpecifiedMaxMemoryTransferSize (user_specified_max);
- result.SetStatus (eReturnStatusSuccessFinishResult);
- return true;
- }
- }
- result.SetStatus (eReturnStatusFailed);
- return false;
+ CommandObjectProcessGDBRemotePacketXferSize(CommandInterpreter &interpreter)
+ : CommandObjectParsed(
+ interpreter, "process plugin packet xfer-size",
+ "Maximum size that lldb will try to read/write one one chunk.",
+ NULL) {}
+
+ ~CommandObjectProcessGDBRemotePacketXferSize() {}
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ result.AppendErrorWithFormat("'%s' takes an argument to specify the max "
+ "amount to be transferred when "
+ "reading/writing",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process) {
+ const char *packet_size = command.GetArgumentAtIndex(0);
+ errno = 0;
+ uint64_t user_specified_max = strtoul(packet_size, NULL, 10);
+ if (errno == 0 && user_specified_max != 0) {
+ process->SetUserSpecifiedMaxMemoryTransferSize(user_specified_max);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ return true;
+ }
}
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
};
-
-class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed
-{
+class CommandObjectProcessGDBRemotePacketSend : public CommandObjectParsed {
private:
-
public:
- CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter) :
- CommandObjectParsed (interpreter,
- "process plugin packet send",
- "Send a custom packet through the GDB remote protocol and print the answer. "
- "The packet header and footer will automatically be added to the packet prior to sending and stripped from the result.",
- NULL)
- {
- }
-
- ~CommandObjectProcessGDBRemotePacketSend ()
- {
- }
-
- bool
- DoExecute (Args& command, CommandReturnObject &result) override
- {
- const size_t argc = command.GetArgumentCount();
- if (argc == 0)
- {
- result.AppendErrorWithFormat ("'%s' takes a one or more packet content arguments", m_cmd_name.c_str());
- result.SetStatus (eReturnStatusFailed);
- return false;
+ CommandObjectProcessGDBRemotePacketSend(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "process plugin packet send",
+ "Send a custom packet through the GDB remote "
+ "protocol and print the answer. "
+ "The packet header and footer will automatically "
+ "be added to the packet prior to sending and "
+ "stripped from the result.",
+ NULL) {}
+
+ ~CommandObjectProcessGDBRemotePacketSend() {}
+
+ bool DoExecute(Args &command, CommandReturnObject &result) override {
+ const size_t argc = command.GetArgumentCount();
+ if (argc == 0) {
+ result.AppendErrorWithFormat(
+ "'%s' takes a one or more packet content arguments",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process) {
+ for (size_t i = 0; i < argc; ++i) {
+ const char *packet_cstr = command.GetArgumentAtIndex(0);
+ bool send_async = true;
+ StringExtractorGDBRemote response;
+ process->GetGDBRemote().SendPacketAndWaitForResponse(
+ packet_cstr, response, send_async);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ Stream &output_strm = result.GetOutputStream();
+ output_strm.Printf(" packet: %s\n", packet_cstr);
+ std::string &response_str = response.GetStringRef();
+
+ if (strstr(packet_cstr, "qGetProfileData") != NULL) {
+ response_str = process->HarmonizeThreadIdsForProfileData(response);
}
- ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process)
- {
- for (size_t i=0; i<argc; ++ i)
- {
- const char *packet_cstr = command.GetArgumentAtIndex(0);
- bool send_async = true;
- StringExtractorGDBRemote response;
- process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async);
- result.SetStatus (eReturnStatusSuccessFinishResult);
- Stream &output_strm = result.GetOutputStream();
- output_strm.Printf (" packet: %s\n", packet_cstr);
- std::string &response_str = response.GetStringRef();
-
- if (strstr(packet_cstr, "qGetProfileData") != NULL)
- {
- response_str = process->GetGDBRemote().HarmonizeThreadIdsForProfileData(process, response);
- }
-
- if (response_str.empty())
- output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
- else
- output_strm.Printf ("response: %s\n", response.GetStringRef().c_str());
- }
- }
- return true;
+ if (response_str.empty())
+ output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n");
+ else
+ output_strm.Printf("response: %s\n", response.GetStringRef().c_str());
+ }
}
+ return true;
+ }
};
-class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw
-{
+class CommandObjectProcessGDBRemotePacketMonitor : public CommandObjectRaw {
private:
-
public:
- CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter) :
- CommandObjectRaw (interpreter,
- "process plugin packet monitor",
- "Send a qRcmd packet through the GDB remote protocol and print the response."
- "The argument passed to this command will be hex encoded into a valid 'qRcmd' packet, sent and the response will be printed.",
- NULL)
- {
- }
-
- ~CommandObjectProcessGDBRemotePacketMonitor ()
- {
- }
-
- bool
- DoExecute (const char *command, CommandReturnObject &result) override
- {
- if (command == NULL || command[0] == '\0')
- {
- result.AppendErrorWithFormat ("'%s' takes a command string argument", m_cmd_name.c_str());
- result.SetStatus (eReturnStatusFailed);
- return false;
- }
-
- ProcessGDBRemote *process = (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
- if (process)
- {
- StreamString packet;
- packet.PutCString("qRcmd,");
- packet.PutBytesAsRawHex8(command, strlen(command));
- const char *packet_cstr = packet.GetString().c_str();
-
- bool send_async = true;
- StringExtractorGDBRemote response;
- process->GetGDBRemote().SendPacketAndWaitForResponse(packet_cstr, response, send_async);
- result.SetStatus (eReturnStatusSuccessFinishResult);
- Stream &output_strm = result.GetOutputStream();
- output_strm.Printf (" packet: %s\n", packet_cstr);
- const std::string &response_str = response.GetStringRef();
-
- if (response_str.empty())
- output_strm.PutCString ("response: \nerror: UNIMPLEMENTED\n");
- else
- output_strm.Printf ("response: %s\n", response.GetStringRef().c_str());
- }
- return true;
+ CommandObjectProcessGDBRemotePacketMonitor(CommandInterpreter &interpreter)
+ : CommandObjectRaw(interpreter, "process plugin packet monitor",
+ "Send a qRcmd packet through the GDB remote protocol "
+ "and print the response."
+ "The argument passed to this command will be hex "
+ "encoded into a valid 'qRcmd' packet, sent and the "
+ "response will be printed.") {}
+
+ ~CommandObjectProcessGDBRemotePacketMonitor() {}
+
+ bool DoExecute(const char *command, CommandReturnObject &result) override {
+ if (command == NULL || command[0] == '\0') {
+ result.AppendErrorWithFormat("'%s' takes a command string argument",
+ m_cmd_name.c_str());
+ result.SetStatus(eReturnStatusFailed);
+ return false;
+ }
+
+ ProcessGDBRemote *process =
+ (ProcessGDBRemote *)m_interpreter.GetExecutionContext().GetProcessPtr();
+ if (process) {
+ StreamString packet;
+ packet.PutCString("qRcmd,");
+ packet.PutBytesAsRawHex8(command, strlen(command));
+
+ bool send_async = true;
+ StringExtractorGDBRemote response;
+ process->GetGDBRemote().SendPacketAndWaitForResponse(
+ packet.GetString(), response, send_async);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ Stream &output_strm = result.GetOutputStream();
+ output_strm.Printf(" packet: %s\n", packet.GetData());
+ const std::string &response_str = response.GetStringRef();
+
+ if (response_str.empty())
+ output_strm.PutCString("response: \nerror: UNIMPLEMENTED\n");
+ else
+ output_strm.Printf("response: %s\n", response.GetStringRef().c_str());
}
+ return true;
+ }
};
-class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword
-{
+class CommandObjectProcessGDBRemotePacket : public CommandObjectMultiword {
private:
-
public:
- CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter) :
- CommandObjectMultiword (interpreter,
- "process plugin packet",
- "Commands that deal with GDB remote packets.",
- NULL)
- {
- LoadSubCommand ("history", CommandObjectSP (new CommandObjectProcessGDBRemotePacketHistory (interpreter)));
- LoadSubCommand ("send", CommandObjectSP (new CommandObjectProcessGDBRemotePacketSend (interpreter)));
- LoadSubCommand ("monitor", CommandObjectSP (new CommandObjectProcessGDBRemotePacketMonitor (interpreter)));
- LoadSubCommand ("xfer-size", CommandObjectSP (new CommandObjectProcessGDBRemotePacketXferSize (interpreter)));
- LoadSubCommand ("speed-test", CommandObjectSP (new CommandObjectProcessGDBRemoteSpeedTest (interpreter)));
- }
-
- ~CommandObjectProcessGDBRemotePacket ()
- {
- }
+ CommandObjectProcessGDBRemotePacket(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(interpreter, "process plugin packet",
+ "Commands that deal with GDB remote packets.",
+ NULL) {
+ LoadSubCommand(
+ "history",
+ CommandObjectSP(
+ new CommandObjectProcessGDBRemotePacketHistory(interpreter)));
+ LoadSubCommand(
+ "send", CommandObjectSP(
+ new CommandObjectProcessGDBRemotePacketSend(interpreter)));
+ LoadSubCommand(
+ "monitor",
+ CommandObjectSP(
+ new CommandObjectProcessGDBRemotePacketMonitor(interpreter)));
+ LoadSubCommand(
+ "xfer-size",
+ CommandObjectSP(
+ new CommandObjectProcessGDBRemotePacketXferSize(interpreter)));
+ LoadSubCommand("speed-test",
+ CommandObjectSP(new CommandObjectProcessGDBRemoteSpeedTest(
+ interpreter)));
+ }
+
+ ~CommandObjectProcessGDBRemotePacket() {}
};
-class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword
-{
+class CommandObjectMultiwordProcessGDBRemote : public CommandObjectMultiword {
public:
- CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter)
- : CommandObjectMultiword(interpreter, "process plugin", "Commands for operating on a ProcessGDBRemote process.",
- "process plugin <subcommand> [<subcommand-options>]")
- {
- LoadSubCommand ("packet", CommandObjectSP (new CommandObjectProcessGDBRemotePacket (interpreter)));
- }
-
- ~CommandObjectMultiwordProcessGDBRemote ()
- {
- }
+ CommandObjectMultiwordProcessGDBRemote(CommandInterpreter &interpreter)
+ : CommandObjectMultiword(
+ interpreter, "process plugin",
+ "Commands for operating on a ProcessGDBRemote process.",
+ "process plugin <subcommand> [<subcommand-options>]") {
+ LoadSubCommand(
+ "packet",
+ CommandObjectSP(new CommandObjectProcessGDBRemotePacket(interpreter)));
+ }
+
+ ~CommandObjectMultiwordProcessGDBRemote() {}
};
-CommandObject *
-ProcessGDBRemote::GetPluginCommandObject()
-{
- if (!m_command_sp)
- m_command_sp.reset (new CommandObjectMultiwordProcessGDBRemote (GetTarget().GetDebugger().GetCommandInterpreter()));
- return m_command_sp.get();
+CommandObject *ProcessGDBRemote::GetPluginCommandObject() {
+ if (!m_command_sp)
+ m_command_sp.reset(new CommandObjectMultiwordProcessGDBRemote(
+ GetTarget().GetDebugger().GetCommandInterpreter()));
+ return m_command_sp.get();
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 6d37396..6423abc 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -24,462 +24,425 @@
#include "lldb/Core/Broadcaster.h"
#include "lldb/Core/ConstString.h"
#include "lldb/Core/Error.h"
+#include "lldb/Core/LoadedModuleInfoList.h"
+#include "lldb/Core/ModuleSpec.h"
#include "lldb/Core/StreamString.h"
#include "lldb/Core/StringList.h"
#include "lldb/Core/StructuredData.h"
#include "lldb/Core/ThreadSafeValue.h"
-#include "lldb/Core/LoadedModuleInfoList.h"
#include "lldb/Host/HostThread.h"
-#include "lldb/lldb-private-forward.h"
-#include "lldb/Utility/StringExtractor.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Thread.h"
+#include "lldb/Utility/StringExtractor.h"
+#include "lldb/lldb-private-forward.h"
#include "GDBRemoteCommunicationClient.h"
#include "GDBRemoteRegisterContext.h"
+#include "llvm/ADT/DenseMap.h"
+
namespace lldb_private {
namespace process_gdb_remote {
class ThreadGDBRemote;
-class ProcessGDBRemote : public Process
-{
+class ProcessGDBRemote : public Process,
+ private GDBRemoteClientBase::ContinueDelegate {
public:
- ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
+ ProcessGDBRemote(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp);
- ~ProcessGDBRemote() override;
+ ~ProcessGDBRemote() override;
- static lldb::ProcessSP
- CreateInstance (lldb::TargetSP target_sp,
- lldb::ListenerSP listener_sp,
- const FileSpec *crash_file_path);
+ static lldb::ProcessSP CreateInstance(lldb::TargetSP target_sp,
+ lldb::ListenerSP listener_sp,
+ const FileSpec *crash_file_path);
- static void
- Initialize();
+ static void Initialize();
- static void
- DebuggerInitialize (Debugger &debugger);
+ static void DebuggerInitialize(Debugger &debugger);
- static void
- Terminate();
+ static void Terminate();
- static ConstString
- GetPluginNameStatic();
+ static ConstString GetPluginNameStatic();
- static const char *
- GetPluginDescriptionStatic();
+ static const char *GetPluginDescriptionStatic();
- //------------------------------------------------------------------
- // Check if a given Process
- //------------------------------------------------------------------
- bool
- CanDebug (lldb::TargetSP target_sp, bool plugin_specified_by_name) override;
+ //------------------------------------------------------------------
+ // Check if a given Process
+ //------------------------------------------------------------------
+ bool CanDebug(lldb::TargetSP target_sp,
+ bool plugin_specified_by_name) override;
- CommandObject *
- GetPluginCommandObject() override;
+ CommandObject *GetPluginCommandObject() override;
- //------------------------------------------------------------------
- // Creating a new process, or attaching to an existing one
- //------------------------------------------------------------------
- Error
- WillLaunch (Module* module) override;
+ //------------------------------------------------------------------
+ // Creating a new process, or attaching to an existing one
+ //------------------------------------------------------------------
+ Error WillLaunch(Module *module) override;
- Error
- DoLaunch (Module *exe_module, ProcessLaunchInfo &launch_info) override;
+ Error DoLaunch(Module *exe_module, ProcessLaunchInfo &launch_info) override;
- void
- DidLaunch () override;
-
- Error
- WillAttachToProcessWithID (lldb::pid_t pid) override;
-
- Error
- WillAttachToProcessWithName (const char *process_name, bool wait_for_launch) override;
+ void DidLaunch() override;
- Error
- DoConnectRemote (Stream *strm, const char *remote_url) override;
-
- Error
- WillLaunchOrAttach ();
-
- Error
- DoAttachToProcessWithID (lldb::pid_t pid, const ProcessAttachInfo &attach_info) override;
-
- Error
- DoAttachToProcessWithName (const char *process_name,
- const ProcessAttachInfo &attach_info) override;
-
- void
- DidAttach (ArchSpec &process_arch) override;
-
- //------------------------------------------------------------------
- // PluginInterface protocol
- //------------------------------------------------------------------
- ConstString
- GetPluginName() override;
-
- uint32_t
- GetPluginVersion() override;
-
- //------------------------------------------------------------------
- // Process Control
- //------------------------------------------------------------------
- Error
- WillResume () override;
-
- Error
- DoResume () override;
-
- Error
- DoHalt (bool &caused_stop) override;
-
- Error
- DoDetach (bool keep_stopped) override;
-
- bool
- DetachRequiresHalt() override { return true; }
-
- Error
- DoSignal (int signal) override;
-
- Error
- DoDestroy () override;
-
- void
- RefreshStateAfterStop() override;
-
- void
- SetUnixSignals(const lldb::UnixSignalsSP &signals_sp);
-
- //------------------------------------------------------------------
- // Process Queries
- //------------------------------------------------------------------
- bool
- IsAlive () override;
-
- lldb::addr_t
- GetImageInfoAddress() override;
-
- void
- WillPublicStop () override;
-
- //------------------------------------------------------------------
- // Process Memory
- //------------------------------------------------------------------
- size_t
- DoReadMemory (lldb::addr_t addr, void *buf, size_t size, Error &error) override;
-
- size_t
- DoWriteMemory (lldb::addr_t addr, const void *buf, size_t size, Error &error) override;
-
- lldb::addr_t
- DoAllocateMemory (size_t size, uint32_t permissions, Error &error) override;
-
- Error
- GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &region_info) override;
-
- Error
- DoDeallocateMemory (lldb::addr_t ptr) override;
-
- //------------------------------------------------------------------
- // Process STDIO
- //------------------------------------------------------------------
- size_t
- PutSTDIN (const char *buf, size_t buf_size, Error &error) override;
-
- //----------------------------------------------------------------------
- // Process Breakpoints
- //----------------------------------------------------------------------
- Error
- EnableBreakpointSite (BreakpointSite *bp_site) override;
-
- Error
- DisableBreakpointSite (BreakpointSite *bp_site) override;
-
- //----------------------------------------------------------------------
- // Process Watchpoints
- //----------------------------------------------------------------------
- Error
- EnableWatchpoint (Watchpoint *wp, bool notify = true) override;
-
- Error
- DisableWatchpoint (Watchpoint *wp, bool notify = true) override;
-
- Error
- GetWatchpointSupportInfo (uint32_t &num) override;
-
- Error
- GetWatchpointSupportInfo (uint32_t &num, bool& after) override;
-
- bool
- StartNoticingNewThreads() override;
-
- bool
- StopNoticingNewThreads() override;
-
- GDBRemoteCommunicationClient &
- GetGDBRemote()
- {
- return m_gdb_comm;
- }
-
- Error
- SendEventData(const char *data) override;
+ Error WillAttachToProcessWithID(lldb::pid_t pid) override;
+
+ Error WillAttachToProcessWithName(const char *process_name,
+ bool wait_for_launch) override;
+
+ Error DoConnectRemote(Stream *strm, llvm::StringRef remote_url) override;
+
+ Error WillLaunchOrAttach();
+
+ Error DoAttachToProcessWithID(lldb::pid_t pid,
+ const ProcessAttachInfo &attach_info) override;
+
+ Error
+ DoAttachToProcessWithName(const char *process_name,
+ const ProcessAttachInfo &attach_info) override;
+
+ void DidAttach(ArchSpec &process_arch) override;
+
+ //------------------------------------------------------------------
+ // PluginInterface protocol
+ //------------------------------------------------------------------
+ ConstString GetPluginName() override;
+
+ uint32_t GetPluginVersion() override;
+
+ //------------------------------------------------------------------
+ // Process Control
+ //------------------------------------------------------------------
+ Error WillResume() override;
+
+ Error DoResume() override;
+
+ Error DoHalt(bool &caused_stop) override;
+
+ Error DoDetach(bool keep_stopped) override;
+
+ bool DetachRequiresHalt() override { return true; }
+
+ Error DoSignal(int signal) override;
+
+ Error DoDestroy() override;
+
+ void RefreshStateAfterStop() override;
+
+ void SetUnixSignals(const lldb::UnixSignalsSP &signals_sp);
+
+ //------------------------------------------------------------------
+ // Process Queries
+ //------------------------------------------------------------------
+ bool IsAlive() override;
+
+ lldb::addr_t GetImageInfoAddress() override;
+
+ void WillPublicStop() override;
+
+ //------------------------------------------------------------------
+ // Process Memory
+ //------------------------------------------------------------------
+ size_t DoReadMemory(lldb::addr_t addr, void *buf, size_t size,
+ Error &error) override;
+
+ size_t DoWriteMemory(lldb::addr_t addr, const void *buf, size_t size,
+ Error &error) override;
+
+ lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions,
+ Error &error) override;
+
+ Error GetMemoryRegionInfo(lldb::addr_t load_addr,
+ MemoryRegionInfo &region_info) override;
- //----------------------------------------------------------------------
- // Override DidExit so we can disconnect from the remote GDB server
- //----------------------------------------------------------------------
- void
- DidExit () override;
+ Error DoDeallocateMemory(lldb::addr_t ptr) override;
- void
- SetUserSpecifiedMaxMemoryTransferSize (uint64_t user_specified_max);
+ //------------------------------------------------------------------
+ // Process STDIO
+ //------------------------------------------------------------------
+ size_t PutSTDIN(const char *buf, size_t buf_size, Error &error) override;
- bool
- GetModuleSpec(const FileSpec& module_file_spec,
- const ArchSpec& arch,
- ModuleSpec &module_spec) override;
+ //----------------------------------------------------------------------
+ // Process Breakpoints
+ //----------------------------------------------------------------------
+ Error EnableBreakpointSite(BreakpointSite *bp_site) override;
- bool
- GetHostOSVersion(uint32_t &major,
- uint32_t &minor,
- uint32_t &update) override;
+ Error DisableBreakpointSite(BreakpointSite *bp_site) override;
- size_t
- LoadModules(LoadedModuleInfoList &module_list) override;
+ //----------------------------------------------------------------------
+ // Process Watchpoints
+ //----------------------------------------------------------------------
+ Error EnableWatchpoint(Watchpoint *wp, bool notify = true) override;
- size_t
- LoadModules() override;
+ Error DisableWatchpoint(Watchpoint *wp, bool notify = true) override;
- Error
- GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr) override;
+ Error GetWatchpointSupportInfo(uint32_t &num) override;
- void
- ModulesDidLoad (ModuleList &module_list) override;
+ Error GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
- StructuredData::ObjectSP
- GetLoadedDynamicLibrariesInfos (lldb::addr_t image_list_address, lldb::addr_t image_count) override;
+ bool StartNoticingNewThreads() override;
+
+ bool StopNoticingNewThreads() override;
+
+ GDBRemoteCommunicationClient &GetGDBRemote() { return m_gdb_comm; }
+
+ Error SendEventData(const char *data) override;
+
+ //----------------------------------------------------------------------
+ // Override DidExit so we can disconnect from the remote GDB server
+ //----------------------------------------------------------------------
+ void DidExit() override;
+
+ void SetUserSpecifiedMaxMemoryTransferSize(uint64_t user_specified_max);
+
+ bool GetModuleSpec(const FileSpec &module_file_spec, const ArchSpec &arch,
+ ModuleSpec &module_spec) override;
+
+ void PrefetchModuleSpecs(llvm::ArrayRef<FileSpec> module_file_specs,
+ const llvm::Triple &triple) override;
+
+ bool GetHostOSVersion(uint32_t &major, uint32_t &minor,
+ uint32_t &update) override;
+
+ size_t LoadModules(LoadedModuleInfoList &module_list) override;
+
+ size_t LoadModules() override;
+
+ Error GetFileLoadAddress(const FileSpec &file, bool &is_loaded,
+ lldb::addr_t &load_addr) override;
+
+ void ModulesDidLoad(ModuleList &module_list) override;
+
+ StructuredData::ObjectSP
+ GetLoadedDynamicLibrariesInfos(lldb::addr_t image_list_address,
+ lldb::addr_t image_count) override;
+
+ Error
+ ConfigureStructuredData(const ConstString &type_name,
+ const StructuredData::ObjectSP &config_sp) override;
+
+ StructuredData::ObjectSP GetLoadedDynamicLibrariesInfos() override;
+
+ StructuredData::ObjectSP GetLoadedDynamicLibrariesInfos(
+ const std::vector<lldb::addr_t> &load_addresses) override;
+
+ StructuredData::ObjectSP
+ GetLoadedDynamicLibrariesInfos_sender(StructuredData::ObjectSP args);
+
+ StructuredData::ObjectSP GetSharedCacheInfo() override;
+
+ std::string HarmonizeThreadIdsForProfileData(
+ StringExtractorGDBRemote &inputStringExtractor);
protected:
- friend class ThreadGDBRemote;
- friend class GDBRemoteCommunicationClient;
- friend class GDBRemoteRegisterContext;
-
- //------------------------------------------------------------------
- /// Broadcaster event bits definitions.
- //------------------------------------------------------------------
- enum
- {
- eBroadcastBitAsyncContinue = (1 << 0),
- eBroadcastBitAsyncThreadShouldExit = (1 << 1),
- eBroadcastBitAsyncThreadDidExit = (1 << 2)
- };
-
- Flags m_flags; // Process specific flags (see eFlags enums)
- GDBRemoteCommunicationClient m_gdb_comm;
- std::atomic<lldb::pid_t> m_debugserver_pid;
- std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet stack replaces the last stop packet variable
- std::recursive_mutex m_last_stop_packet_mutex;
- GDBRemoteDynamicRegisterInfo m_register_info;
- Broadcaster m_async_broadcaster;
- lldb::ListenerSP m_async_listener_sp;
- HostThread m_async_thread;
- std::recursive_mutex m_async_thread_state_mutex;
- typedef std::vector<lldb::tid_t> tid_collection;
- typedef std::vector< std::pair<lldb::tid_t,int> > tid_sig_collection;
- typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
- typedef std::map<uint32_t, std::string> ExpeditedRegisterMap;
- tid_collection m_thread_ids; // Thread IDs for all threads. This list gets updated after stopping
- std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads.
- StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads that have valid stop infos
- StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited registers and memory for all threads if "jThreadsInfo" packet is supported
- tid_collection m_continue_c_tids; // 'c' for continue
- tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
- tid_collection m_continue_s_tids; // 's' for step
- tid_sig_collection m_continue_S_tids; // 'S' for step with signal
- uint64_t m_max_memory_size; // The maximum number of bytes to read/write when reading and writing memory
- uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote gdb stub can handle
- MMapMap m_addr_to_mmap_size;
- lldb::BreakpointSP m_thread_create_bp_sp;
- bool m_waiting_for_attach;
- bool m_destroy_tried_resuming;
- lldb::CommandObjectSP m_command_sp;
- int64_t m_breakpoint_pc_offset;
- lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
-
- //----------------------------------------------------------------------
- // Accessors
- //----------------------------------------------------------------------
- bool
- IsRunning ( lldb::StateType state )
- {
- return state == lldb::eStateRunning || IsStepping(state);
- }
+ friend class ThreadGDBRemote;
+ friend class GDBRemoteCommunicationClient;
+ friend class GDBRemoteRegisterContext;
+
+ //------------------------------------------------------------------
+ /// Broadcaster event bits definitions.
+ //------------------------------------------------------------------
+ enum {
+ eBroadcastBitAsyncContinue = (1 << 0),
+ eBroadcastBitAsyncThreadShouldExit = (1 << 1),
+ eBroadcastBitAsyncThreadDidExit = (1 << 2)
+ };
- bool
- IsStepping ( lldb::StateType state)
- {
- return state == lldb::eStateStepping;
- }
+ Flags m_flags; // Process specific flags (see eFlags enums)
+ GDBRemoteCommunicationClient m_gdb_comm;
+ std::atomic<lldb::pid_t> m_debugserver_pid;
+ std::vector<StringExtractorGDBRemote> m_stop_packet_stack; // The stop packet
+ // stack replaces
+ // the last stop
+ // packet variable
+ std::recursive_mutex m_last_stop_packet_mutex;
+ GDBRemoteDynamicRegisterInfo m_register_info;
+ Broadcaster m_async_broadcaster;
+ lldb::ListenerSP m_async_listener_sp;
+ HostThread m_async_thread;
+ std::recursive_mutex m_async_thread_state_mutex;
+ typedef std::vector<lldb::tid_t> tid_collection;
+ typedef std::vector<std::pair<lldb::tid_t, int>> tid_sig_collection;
+ typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
+ typedef std::map<uint32_t, std::string> ExpeditedRegisterMap;
+ tid_collection m_thread_ids; // Thread IDs for all threads. This list gets
+ // updated after stopping
+ std::vector<lldb::addr_t> m_thread_pcs; // PC values for all the threads.
+ StructuredData::ObjectSP m_jstopinfo_sp; // Stop info only for any threads
+ // that have valid stop infos
+ StructuredData::ObjectSP m_jthreadsinfo_sp; // Full stop info, expedited
+ // registers and memory for all
+ // threads if "jThreadsInfo"
+ // packet is supported
+ tid_collection m_continue_c_tids; // 'c' for continue
+ tid_sig_collection m_continue_C_tids; // 'C' for continue with signal
+ tid_collection m_continue_s_tids; // 's' for step
+ tid_sig_collection m_continue_S_tids; // 'S' for step with signal
+ uint64_t m_max_memory_size; // The maximum number of bytes to read/write when
+ // reading and writing memory
+ uint64_t m_remote_stub_max_memory_size; // The maximum memory size the remote
+ // gdb stub can handle
+ MMapMap m_addr_to_mmap_size;
+ lldb::BreakpointSP m_thread_create_bp_sp;
+ bool m_waiting_for_attach;
+ bool m_destroy_tried_resuming;
+ lldb::CommandObjectSP m_command_sp;
+ int64_t m_breakpoint_pc_offset;
+ lldb::tid_t m_initial_tid; // The initial thread ID, given by stub on attach
- bool
- CanResume ( lldb::StateType state)
- {
- return state == lldb::eStateStopped;
- }
+ //----------------------------------------------------------------------
+ // Accessors
+ //----------------------------------------------------------------------
+ bool IsRunning(lldb::StateType state) {
+ return state == lldb::eStateRunning || IsStepping(state);
+ }
- bool
- HasExited (lldb::StateType state)
- {
- return state == lldb::eStateExited;
- }
+ bool IsStepping(lldb::StateType state) {
+ return state == lldb::eStateStepping;
+ }
- bool
- ProcessIDIsValid ( ) const;
+ bool CanResume(lldb::StateType state) { return state == lldb::eStateStopped; }
- void
- Clear ( );
+ bool HasExited(lldb::StateType state) { return state == lldb::eStateExited; }
- Flags &
- GetFlags ()
- {
- return m_flags;
- }
+ bool ProcessIDIsValid() const;
- const Flags &
- GetFlags () const
- {
- return m_flags;
- }
+ void Clear();
+
+ Flags &GetFlags() { return m_flags; }
- bool
- UpdateThreadList (ThreadList &old_thread_list,
- ThreadList &new_thread_list) override;
+ const Flags &GetFlags() const { return m_flags; }
- Error
- EstablishConnectionIfNeeded (const ProcessInfo &process_info);
+ bool UpdateThreadList(ThreadList &old_thread_list,
+ ThreadList &new_thread_list) override;
- Error
- LaunchAndConnectToDebugserver (const ProcessInfo &process_info);
+ Error EstablishConnectionIfNeeded(const ProcessInfo &process_info);
- void
- KillDebugserverProcess ();
+ Error LaunchAndConnectToDebugserver(const ProcessInfo &process_info);
- void
- BuildDynamicRegisterInfo (bool force);
+ void KillDebugserverProcess();
- void
- SetLastStopPacket (const StringExtractorGDBRemote &response);
+ void BuildDynamicRegisterInfo(bool force);
- bool
- ParsePythonTargetDefinition(const FileSpec &target_definition_fspec);
+ void SetLastStopPacket(const StringExtractorGDBRemote &response);
- const lldb::DataBufferSP
- GetAuxvData() override;
+ bool ParsePythonTargetDefinition(const FileSpec &target_definition_fspec);
- StructuredData::ObjectSP
- GetExtendedInfoForThread (lldb::tid_t tid);
+ const lldb::DataBufferSP GetAuxvData() override;
- void
- GetMaxMemorySize();
+ StructuredData::ObjectSP GetExtendedInfoForThread(lldb::tid_t tid);
- bool
- CalculateThreadStopInfo (ThreadGDBRemote *thread);
+ void GetMaxMemorySize();
- size_t
- UpdateThreadPCsFromStopReplyThreadsValue (std::string &value);
+ bool CalculateThreadStopInfo(ThreadGDBRemote *thread);
- size_t
- UpdateThreadIDsFromStopReplyThreadsValue (std::string &value);
+ size_t UpdateThreadPCsFromStopReplyThreadsValue(std::string &value);
- bool
- HandleNotifyPacket(StringExtractorGDBRemote &packet);
+ size_t UpdateThreadIDsFromStopReplyThreadsValue(std::string &value);
- bool
- StartAsyncThread ();
+ bool HandleNotifyPacket(StringExtractorGDBRemote &packet);
- void
- StopAsyncThread ();
+ bool StartAsyncThread();
- static lldb::thread_result_t
- AsyncThread (void *arg);
+ void StopAsyncThread();
- static bool
- MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp, lldb::pid_t pid, bool exited, int signo,
- int exit_status);
+ static lldb::thread_result_t AsyncThread(void *arg);
- lldb::StateType
- SetThreadStopInfo (StringExtractor& stop_packet);
+ static bool
+ MonitorDebugserverProcess(std::weak_ptr<ProcessGDBRemote> process_wp,
+ lldb::pid_t pid, bool exited, int signo,
+ int exit_status);
- bool
- GetThreadStopInfoFromJSON (ThreadGDBRemote *thread, const StructuredData::ObjectSP &thread_infos_sp);
+ lldb::StateType SetThreadStopInfo(StringExtractor &stop_packet);
- lldb::ThreadSP
- SetThreadStopInfo (StructuredData::Dictionary *thread_dict);
+ bool
+ GetThreadStopInfoFromJSON(ThreadGDBRemote *thread,
+ const StructuredData::ObjectSP &thread_infos_sp);
- lldb::ThreadSP
- SetThreadStopInfo (lldb::tid_t tid,
- ExpeditedRegisterMap &expedited_register_map,
- uint8_t signo,
- const std::string &thread_name,
- const std::string &reason,
- const std::string &description,
- uint32_t exc_type,
- const std::vector<lldb::addr_t> &exc_data,
- lldb::addr_t thread_dispatch_qaddr,
- bool queue_vars_valid,
- lldb_private::LazyBool associated_with_libdispatch_queue,
- lldb::addr_t dispatch_queue_t,
- std::string &queue_name,
- lldb::QueueKind queue_kind,
- uint64_t queue_serial);
+ lldb::ThreadSP SetThreadStopInfo(StructuredData::Dictionary *thread_dict);
- void
- HandleStopReplySequence ();
+ lldb::ThreadSP
+ SetThreadStopInfo(lldb::tid_t tid,
+ ExpeditedRegisterMap &expedited_register_map, uint8_t signo,
+ const std::string &thread_name, const std::string &reason,
+ const std::string &description, uint32_t exc_type,
+ const std::vector<lldb::addr_t> &exc_data,
+ lldb::addr_t thread_dispatch_qaddr, bool queue_vars_valid,
+ lldb_private::LazyBool associated_with_libdispatch_queue,
+ lldb::addr_t dispatch_queue_t, std::string &queue_name,
+ lldb::QueueKind queue_kind, uint64_t queue_serial);
- void
- ClearThreadIDList ();
+ void HandleStopReplySequence();
- bool
- UpdateThreadIDList ();
+ void ClearThreadIDList();
- void
- DidLaunchOrAttach (ArchSpec& process_arch);
+ bool UpdateThreadIDList();
- Error
- ConnectToDebugserver (const char *host_port);
+ void DidLaunchOrAttach(ArchSpec &process_arch);
- const char *
- GetDispatchQueueNameForThread (lldb::addr_t thread_dispatch_qaddr,
- std::string &dispatch_queue_name);
+ Error ConnectToDebugserver(llvm::StringRef host_port);
- DynamicLoader *
- GetDynamicLoader () override;
+ const char *GetDispatchQueueNameForThread(lldb::addr_t thread_dispatch_qaddr,
+ std::string &dispatch_queue_name);
- // Query remote GDBServer for register information
- bool
- GetGDBServerRegisterInfo (ArchSpec &arch);
+ DynamicLoader *GetDynamicLoader() override;
- // Query remote GDBServer for a detailed loaded library list
- Error
- GetLoadedModuleList (LoadedModuleInfoList &);
+ // Query remote GDBServer for register information
+ bool GetGDBServerRegisterInfo(ArchSpec &arch);
- lldb::ModuleSP
- LoadModuleAtAddress (const FileSpec &file, lldb::addr_t link_map, lldb::addr_t base_addr,
- bool value_is_offset);
+ // Query remote GDBServer for a detailed loaded library list
+ Error GetLoadedModuleList(LoadedModuleInfoList &);
+
+ lldb::ModuleSP LoadModuleAtAddress(const FileSpec &file,
+ lldb::addr_t link_map,
+ lldb::addr_t base_addr,
+ bool value_is_offset);
private:
- //------------------------------------------------------------------
- // For ProcessGDBRemote only
- //------------------------------------------------------------------
- static bool
- NewThreadNotifyBreakpointHit (void *baton,
- StoppointCallbackContext *context,
- lldb::user_id_t break_id,
- lldb::user_id_t break_loc_id);
-
- DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote);
+ //------------------------------------------------------------------
+ // For ProcessGDBRemote only
+ //------------------------------------------------------------------
+ std::string m_partial_profile_data;
+ std::map<uint64_t, uint32_t> m_thread_id_to_used_usec_map;
+
+ static bool NewThreadNotifyBreakpointHit(void *baton,
+ StoppointCallbackContext *context,
+ lldb::user_id_t break_id,
+ lldb::user_id_t break_loc_id);
+
+ //------------------------------------------------------------------
+ // ContinueDelegate interface
+ //------------------------------------------------------------------
+ void HandleAsyncStdout(llvm::StringRef out) override;
+ void HandleAsyncMisc(llvm::StringRef data) override;
+ void HandleStopReply() override;
+ void HandleAsyncStructuredDataPacket(llvm::StringRef data) override;
+
+ using ModuleCacheKey = std::pair<std::string, std::string>;
+ // KeyInfo for the cached module spec DenseMap.
+ // The invariant is that all real keys will have the file and architecture
+ // set.
+ // The empty key has an empty file and an empty arch.
+ // The tombstone key has an invalid arch and an empty file.
+ // The comparison and hash functions take the file name and architecture
+ // triple into account.
+ struct ModuleCacheInfo {
+ static ModuleCacheKey getEmptyKey() { return ModuleCacheKey(); }
+
+ static ModuleCacheKey getTombstoneKey() { return ModuleCacheKey("", "T"); }
+
+ static unsigned getHashValue(const ModuleCacheKey &key) {
+ return llvm::hash_combine(key.first, key.second);
+ }
+
+ static bool isEqual(const ModuleCacheKey &LHS, const ModuleCacheKey &RHS) {
+ return LHS == RHS;
+ }
+ };
+
+ llvm::DenseMap<ModuleCacheKey, ModuleSpec, ModuleCacheInfo>
+ m_cached_module_specs;
+
+ DISALLOW_COPY_AND_ASSIGN(ProcessGDBRemote);
};
} // namespace process_gdb_remote
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
index d4726ad..899037a 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.cpp
@@ -11,8 +11,8 @@
#include <mutex>
-#include "lldb/Interpreter/Args.h"
#include "lldb/Core/StreamFile.h"
+#include "lldb/Interpreter/Args.h"
#include "ProcessGDBRemote.h"
@@ -20,196 +20,198 @@ using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
-
// We want to avoid global constructors where code needs to be run so here we
// control access to our static g_log_sp by hiding it in a singleton function
-// that will construct the static g_lob_sp the first time this function is
+// that will construct the static g_lob_sp the first time this function is
// called.
static bool g_log_enabled = false;
-static Log * g_log = NULL;
-static Log *
-GetLog ()
-{
- if (!g_log_enabled)
- return NULL;
- return g_log;
+static Log *g_log = NULL;
+static Log *GetLog() {
+ if (!g_log_enabled)
+ return NULL;
+ return g_log;
}
-void
-ProcessGDBRemoteLog::Initialize()
-{
- static ConstString g_name("gdb-remote");
- static std::once_flag g_once_flag;
-
- std::call_once(g_once_flag, [](){
- Log::Callbacks log_callbacks = {
- DisableLog,
- EnableLog,
- ListLogCategories
- };
-
- Log::RegisterLogChannel (g_name, log_callbacks);
- });
-}
+void ProcessGDBRemoteLog::Initialize() {
+ static ConstString g_name("gdb-remote");
+ static std::once_flag g_once_flag;
-Log *
-ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (uint32_t mask)
-{
- Log *log(GetLog ());
- if (log && mask)
- {
- uint32_t log_mask = log->GetMask().Get();
- if ((log_mask & mask) != mask)
- return NULL;
- }
- return log;
+ std::call_once(g_once_flag, []() {
+ Log::Callbacks log_callbacks = {DisableLog, EnableLog, ListLogCategories};
+
+ Log::RegisterLogChannel(g_name, log_callbacks);
+ });
}
-Log *
-ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (uint32_t mask)
-{
- Log *log(GetLog ());
- if (log && log->GetMask().Get() & mask)
- return log;
- return NULL;
+Log *ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(uint32_t mask) {
+ Log *log(GetLog());
+ if (log && mask) {
+ uint32_t log_mask = log->GetMask().Get();
+ if ((log_mask & mask) != mask)
+ return NULL;
+ }
+ return log;
}
-void
-ProcessGDBRemoteLog::DisableLog (const char **categories, Stream *feedback_strm)
-{
- Log *log (GetLog ());
- if (log)
- {
- uint32_t flag_bits = 0;
-
- if (categories[0] != NULL)
- {
- flag_bits = log->GetMask().Get();
- for (size_t i = 0; categories[i] != NULL; ++i)
- {
- const char *arg = categories[i];
-
-
- if (::strcasecmp (arg, "all") == 0 ) flag_bits &= ~GDBR_LOG_ALL;
- else if (::strcasecmp (arg, "async") == 0 ) flag_bits &= ~GDBR_LOG_ASYNC;
- else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits &= ~GDBR_LOG_BREAKPOINTS;
- else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits &= ~GDBR_LOG_COMM;
- else if (::strcasecmp (arg, "default") == 0 ) flag_bits &= ~GDBR_LOG_DEFAULT;
- else if (::strcasecmp (arg, "packets") == 0 ) flag_bits &= ~GDBR_LOG_PACKETS;
- else if (::strcasecmp (arg, "memory") == 0 ) flag_bits &= ~GDBR_LOG_MEMORY;
- else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT;
- else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG;
- else if (::strcasecmp (arg, "process") == 0 ) flag_bits &= ~GDBR_LOG_PROCESS;
- else if (::strcasecmp (arg, "step") == 0 ) flag_bits &= ~GDBR_LOG_STEP;
- else if (::strcasecmp (arg, "thread") == 0 ) flag_bits &= ~GDBR_LOG_THREAD;
- else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits &= ~GDBR_LOG_VERBOSE;
- else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits &= ~GDBR_LOG_WATCHPOINTS;
- else
- {
- feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
- ListLogCategories (feedback_strm);
- }
-
- }
- }
-
- if (flag_bits == 0)
- g_log_enabled = false;
- else
- log->GetMask().Reset (flag_bits);
- }
-
- return;
+Log *ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet(uint32_t mask) {
+ Log *log(GetLog());
+ if (log && log->GetMask().Get() & mask)
+ return log;
+ return NULL;
}
-Log *
-ProcessGDBRemoteLog::EnableLog (StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm)
-{
- // Try see if there already is a log - that way we can reuse its settings.
- // We could reuse the log in toto, but we don't know that the stream is the same.
+void ProcessGDBRemoteLog::DisableLog(const char **categories,
+ Stream *feedback_strm) {
+ Log *log(GetLog());
+ if (log) {
uint32_t flag_bits = 0;
- if (g_log)
- flag_bits = g_log->GetMask().Get();
-
- // Now make a new log with this stream if one was provided
- if (log_stream_sp)
- {
- if (g_log)
- g_log->SetStream(log_stream_sp);
- else
- g_log = new Log(log_stream_sp);
+
+ if (categories && categories[0]) {
+ flag_bits = log->GetMask().Get();
+ for (size_t i = 0; categories[i] != NULL; ++i) {
+ const char *arg = categories[i];
+
+ if (::strcasecmp(arg, "all") == 0)
+ flag_bits &= ~GDBR_LOG_ALL;
+ else if (::strcasecmp(arg, "async") == 0)
+ flag_bits &= ~GDBR_LOG_ASYNC;
+ else if (::strncasecmp(arg, "break", 5) == 0)
+ flag_bits &= ~GDBR_LOG_BREAKPOINTS;
+ else if (::strncasecmp(arg, "comm", 4) == 0)
+ flag_bits &= ~GDBR_LOG_COMM;
+ else if (::strcasecmp(arg, "default") == 0)
+ flag_bits &= ~GDBR_LOG_DEFAULT;
+ else if (::strcasecmp(arg, "packets") == 0)
+ flag_bits &= ~GDBR_LOG_PACKETS;
+ else if (::strcasecmp(arg, "memory") == 0)
+ flag_bits &= ~GDBR_LOG_MEMORY;
+ else if (::strcasecmp(arg, "data-short") == 0)
+ flag_bits &= ~GDBR_LOG_MEMORY_DATA_SHORT;
+ else if (::strcasecmp(arg, "data-long") == 0)
+ flag_bits &= ~GDBR_LOG_MEMORY_DATA_LONG;
+ else if (::strcasecmp(arg, "process") == 0)
+ flag_bits &= ~GDBR_LOG_PROCESS;
+ else if (::strcasecmp(arg, "step") == 0)
+ flag_bits &= ~GDBR_LOG_STEP;
+ else if (::strcasecmp(arg, "thread") == 0)
+ flag_bits &= ~GDBR_LOG_THREAD;
+ else if (::strcasecmp(arg, "verbose") == 0)
+ flag_bits &= ~GDBR_LOG_VERBOSE;
+ else if (::strncasecmp(arg, "watch", 5) == 0)
+ flag_bits &= ~GDBR_LOG_WATCHPOINTS;
+ else {
+ feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+ ListLogCategories(feedback_strm);
+ }
+ }
}
+ if (flag_bits == 0)
+ g_log_enabled = false;
+ else
+ log->GetMask().Reset(flag_bits);
+ }
+
+ return;
+}
+
+Log *ProcessGDBRemoteLog::EnableLog(StreamSP &log_stream_sp,
+ uint32_t log_options,
+ const char **categories,
+ Stream *feedback_strm) {
+ // Try see if there already is a log - that way we can reuse its settings.
+ // We could reuse the log in toto, but we don't know that the stream is the
+ // same.
+ uint32_t flag_bits = 0;
+ if (g_log)
+ flag_bits = g_log->GetMask().Get();
+
+ // Now make a new log with this stream if one was provided
+ if (log_stream_sp) {
if (g_log)
- {
- bool got_unknown_category = false;
- for (size_t i=0; categories[i] != NULL; ++i)
- {
- const char *arg = categories[i];
-
- if (::strcasecmp (arg, "all") == 0 ) flag_bits |= GDBR_LOG_ALL;
- else if (::strcasecmp (arg, "async") == 0 ) flag_bits |= GDBR_LOG_ASYNC;
- else if (::strncasecmp (arg, "break", 5) == 0 ) flag_bits |= GDBR_LOG_BREAKPOINTS;
- else if (::strncasecmp (arg, "comm", 4) == 0 ) flag_bits |= GDBR_LOG_COMM;
- else if (::strcasecmp (arg, "default") == 0 ) flag_bits |= GDBR_LOG_DEFAULT;
- else if (::strcasecmp (arg, "packets") == 0 ) flag_bits |= GDBR_LOG_PACKETS;
- else if (::strcasecmp (arg, "memory") == 0 ) flag_bits |= GDBR_LOG_MEMORY;
- else if (::strcasecmp (arg, "data-short") == 0 ) flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT;
- else if (::strcasecmp (arg, "data-long") == 0 ) flag_bits |= GDBR_LOG_MEMORY_DATA_LONG;
- else if (::strcasecmp (arg, "process") == 0 ) flag_bits |= GDBR_LOG_PROCESS;
- else if (::strcasecmp (arg, "step") == 0 ) flag_bits |= GDBR_LOG_STEP;
- else if (::strcasecmp (arg, "thread") == 0 ) flag_bits |= GDBR_LOG_THREAD;
- else if (::strcasecmp (arg, "verbose") == 0 ) flag_bits |= GDBR_LOG_VERBOSE;
- else if (::strncasecmp (arg, "watch", 5) == 0 ) flag_bits |= GDBR_LOG_WATCHPOINTS;
- else
- {
- feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
- if (got_unknown_category == false)
- {
- got_unknown_category = true;
- ListLogCategories (feedback_strm);
- }
- }
+ g_log->SetStream(log_stream_sp);
+ else
+ g_log = new Log(log_stream_sp);
+ }
+
+ if (g_log) {
+ bool got_unknown_category = false;
+ for (size_t i = 0; categories[i] != NULL; ++i) {
+ const char *arg = categories[i];
+
+ if (::strcasecmp(arg, "all") == 0)
+ flag_bits |= GDBR_LOG_ALL;
+ else if (::strcasecmp(arg, "async") == 0)
+ flag_bits |= GDBR_LOG_ASYNC;
+ else if (::strncasecmp(arg, "break", 5) == 0)
+ flag_bits |= GDBR_LOG_BREAKPOINTS;
+ else if (::strncasecmp(arg, "comm", 4) == 0)
+ flag_bits |= GDBR_LOG_COMM;
+ else if (::strcasecmp(arg, "default") == 0)
+ flag_bits |= GDBR_LOG_DEFAULT;
+ else if (::strcasecmp(arg, "packets") == 0)
+ flag_bits |= GDBR_LOG_PACKETS;
+ else if (::strcasecmp(arg, "memory") == 0)
+ flag_bits |= GDBR_LOG_MEMORY;
+ else if (::strcasecmp(arg, "data-short") == 0)
+ flag_bits |= GDBR_LOG_MEMORY_DATA_SHORT;
+ else if (::strcasecmp(arg, "data-long") == 0)
+ flag_bits |= GDBR_LOG_MEMORY_DATA_LONG;
+ else if (::strcasecmp(arg, "process") == 0)
+ flag_bits |= GDBR_LOG_PROCESS;
+ else if (::strcasecmp(arg, "step") == 0)
+ flag_bits |= GDBR_LOG_STEP;
+ else if (::strcasecmp(arg, "thread") == 0)
+ flag_bits |= GDBR_LOG_THREAD;
+ else if (::strcasecmp(arg, "verbose") == 0)
+ flag_bits |= GDBR_LOG_VERBOSE;
+ else if (::strncasecmp(arg, "watch", 5) == 0)
+ flag_bits |= GDBR_LOG_WATCHPOINTS;
+ else {
+ feedback_strm->Printf("error: unrecognized log category '%s'\n", arg);
+ if (got_unknown_category == false) {
+ got_unknown_category = true;
+ ListLogCategories(feedback_strm);
}
- if (flag_bits == 0)
- flag_bits = GDBR_LOG_DEFAULT;
- g_log->GetMask().Reset(flag_bits);
- g_log->GetOptions().Reset(log_options);
+ }
}
- g_log_enabled = true;
- return g_log;
+ if (flag_bits == 0)
+ flag_bits = GDBR_LOG_DEFAULT;
+ g_log->GetMask().Reset(flag_bits);
+ g_log->GetOptions().Reset(log_options);
+ }
+ g_log_enabled = true;
+ return g_log;
}
-void
-ProcessGDBRemoteLog::ListLogCategories (Stream *strm)
-{
- strm->Printf ("Logging categories for '%s':\n"
- " all - turn on all available logging categories\n"
- " async - log asynchronous activity\n"
- " break - log breakpoints\n"
- " communication - log communication activity\n"
- " default - enable the default set of logging categories for liblldb\n"
- " packets - log gdb remote packets\n"
- " memory - log memory reads and writes\n"
- " data-short - log memory bytes for memory reads and writes for short transactions only\n"
- " data-long - log memory bytes for memory reads and writes for all transactions\n"
- " process - log process events and activities\n"
- " thread - log thread events and activities\n"
- " step - log step related activities\n"
- " verbose - enable verbose logging\n"
- " watch - log watchpoint related activities\n", ProcessGDBRemote::GetPluginNameStatic().GetCString());
+void ProcessGDBRemoteLog::ListLogCategories(Stream *strm) {
+ strm->Printf(
+ "Logging categories for '%s':\n"
+ " all - turn on all available logging categories\n"
+ " async - log asynchronous activity\n"
+ " break - log breakpoints\n"
+ " communication - log communication activity\n"
+ " default - enable the default set of logging categories for liblldb\n"
+ " packets - log gdb remote packets\n"
+ " memory - log memory reads and writes\n"
+ " data-short - log memory bytes for memory reads and writes for short "
+ "transactions only\n"
+ " data-long - log memory bytes for memory reads and writes for all "
+ "transactions\n"
+ " process - log process events and activities\n"
+ " thread - log thread events and activities\n"
+ " step - log step related activities\n"
+ " verbose - enable verbose logging\n"
+ " watch - log watchpoint related activities\n",
+ ProcessGDBRemote::GetPluginNameStatic().GetCString());
}
-
-void
-ProcessGDBRemoteLog::LogIf (uint32_t mask, const char *format, ...)
-{
- Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (mask));
- if (log)
- {
- va_list args;
- va_start (args, format);
- log->VAPrintf (format, args);
- va_end (args);
- }
+void ProcessGDBRemoteLog::LogIf(uint32_t mask, const char *format, ...) {
+ Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(mask));
+ if (log) {
+ va_list args;
+ va_start(args, format);
+ log->VAPrintf(format, args);
+ va_end(args);
+ }
}
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
index 3cd974d..f5e92b4 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemoteLog.h
@@ -17,50 +17,44 @@
// Project includes
#include "lldb/Core/Log.h"
-#define GDBR_LOG_VERBOSE (1u << 0)
-#define GDBR_LOG_PROCESS (1u << 1)
-#define GDBR_LOG_THREAD (1u << 2)
-#define GDBR_LOG_PACKETS (1u << 3)
-#define GDBR_LOG_MEMORY (1u << 4) // Log memory reads/writes calls
-#define GDBR_LOG_MEMORY_DATA_SHORT (1u << 5) // Log short memory reads/writes bytes
-#define GDBR_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes
-#define GDBR_LOG_BREAKPOINTS (1u << 7)
-#define GDBR_LOG_WATCHPOINTS (1u << 8)
-#define GDBR_LOG_STEP (1u << 9)
-#define GDBR_LOG_COMM (1u << 10)
-#define GDBR_LOG_ASYNC (1u << 11)
-#define GDBR_LOG_ALL (UINT32_MAX)
-#define GDBR_LOG_DEFAULT GDBR_LOG_PACKETS
+#define GDBR_LOG_VERBOSE (1u << 0)
+#define GDBR_LOG_PROCESS (1u << 1)
+#define GDBR_LOG_THREAD (1u << 2)
+#define GDBR_LOG_PACKETS (1u << 3)
+#define GDBR_LOG_MEMORY (1u << 4) // Log memory reads/writes calls
+#define GDBR_LOG_MEMORY_DATA_SHORT \
+ (1u << 5) // Log short memory reads/writes bytes
+#define GDBR_LOG_MEMORY_DATA_LONG (1u << 6) // Log all memory reads/writes bytes
+#define GDBR_LOG_BREAKPOINTS (1u << 7)
+#define GDBR_LOG_WATCHPOINTS (1u << 8)
+#define GDBR_LOG_STEP (1u << 9)
+#define GDBR_LOG_COMM (1u << 10)
+#define GDBR_LOG_ASYNC (1u << 11)
+#define GDBR_LOG_ALL (UINT32_MAX)
+#define GDBR_LOG_DEFAULT GDBR_LOG_PACKETS
namespace lldb_private {
namespace process_gdb_remote {
-class ProcessGDBRemoteLog
-{
+class ProcessGDBRemoteLog {
public:
- static void
- Initialize();
+ static void Initialize();
- static Log *
- GetLogIfAllCategoriesSet(uint32_t mask = 0);
-
- static Log *
- GetLogIfAnyCategoryIsSet (uint32_t mask);
+ static Log *GetLogIfAllCategoriesSet(uint32_t mask = 0);
- static void
- DisableLog (const char **categories, Stream *feedback_strm);
+ static Log *GetLogIfAnyCategoryIsSet(uint32_t mask);
- static Log *
- EnableLog (lldb::StreamSP &log_stream_sp, uint32_t log_options, const char **categories, Stream *feedback_strm);
+ static void DisableLog(const char **categories, Stream *feedback_strm);
- static void
- ListLogCategories (Stream *strm);
+ static Log *EnableLog(lldb::StreamSP &log_stream_sp, uint32_t log_options,
+ const char **categories, Stream *feedback_strm);
- static void
- LogIf (uint32_t mask, const char *format, ...);
+ static void ListLogCategories(Stream *strm);
+
+ static void LogIf(uint32_t mask, const char *format, ...);
};
} // namespace process_gdb_remote
} // namespace lldb_private
-#endif // liblldb_ProcessGDBRemoteLog_h_
+#endif // liblldb_ProcessGDBRemoteLog_h_
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index a4af12c..ab55214 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -7,7 +7,6 @@
//
//===----------------------------------------------------------------------===//
-
#include "ThreadGDBRemote.h"
#include "lldb/Breakpoint/Watchpoint.h"
@@ -36,372 +35,318 @@ using namespace lldb_private::process_gdb_remote;
// Thread Registers
//----------------------------------------------------------------------
-ThreadGDBRemote::ThreadGDBRemote (Process &process, lldb::tid_t tid) :
- Thread(process, tid),
- m_thread_name (),
- m_dispatch_queue_name (),
- m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS),
- m_dispatch_queue_t (LLDB_INVALID_ADDRESS),
- m_queue_kind (eQueueKindUnknown),
- m_queue_serial_number (LLDB_INVALID_QUEUE_ID),
- m_associated_with_libdispatch_queue (eLazyBoolCalculate)
-{
- ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)",
- this,
- process.GetID(),
- GetID());
+ThreadGDBRemote::ThreadGDBRemote(Process &process, lldb::tid_t tid)
+ : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(),
+ m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS),
+ m_dispatch_queue_t(LLDB_INVALID_ADDRESS), m_queue_kind(eQueueKindUnknown),
+ m_queue_serial_number(LLDB_INVALID_QUEUE_ID),
+ m_associated_with_libdispatch_queue(eLazyBoolCalculate) {
+ ProcessGDBRemoteLog::LogIf(
+ GDBR_LOG_THREAD,
+ "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this,
+ process.GetID(), GetID());
}
-ThreadGDBRemote::~ThreadGDBRemote ()
-{
- ProcessSP process_sp(GetProcess());
- ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::~ThreadGDBRemote (pid = %i, tid = 0x%4.4x)",
- this,
- process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID,
- GetID());
- DestroyThread();
+ThreadGDBRemote::~ThreadGDBRemote() {
+ ProcessSP process_sp(GetProcess());
+ ProcessGDBRemoteLog::LogIf(
+ GDBR_LOG_THREAD,
+ "%p: ThreadGDBRemote::~ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this,
+ process_sp ? process_sp->GetID() : LLDB_INVALID_PROCESS_ID, GetID());
+ DestroyThread();
}
-const char *
-ThreadGDBRemote::GetName ()
-{
- if (m_thread_name.empty())
- return NULL;
- return m_thread_name.c_str();
+const char *ThreadGDBRemote::GetName() {
+ if (m_thread_name.empty())
+ return NULL;
+ return m_thread_name.c_str();
}
-void
-ThreadGDBRemote::ClearQueueInfo ()
-{
- m_dispatch_queue_name.clear();
- m_queue_kind = eQueueKindUnknown;
- m_queue_serial_number = 0;
- m_dispatch_queue_t = LLDB_INVALID_ADDRESS;
- m_associated_with_libdispatch_queue = eLazyBoolCalculate;
+void ThreadGDBRemote::ClearQueueInfo() {
+ m_dispatch_queue_name.clear();
+ m_queue_kind = eQueueKindUnknown;
+ m_queue_serial_number = 0;
+ m_dispatch_queue_t = LLDB_INVALID_ADDRESS;
+ m_associated_with_libdispatch_queue = eLazyBoolCalculate;
}
-void
-ThreadGDBRemote::SetQueueInfo (std::string &&queue_name, QueueKind queue_kind, uint64_t queue_serial, addr_t dispatch_queue_t, LazyBool associated_with_libdispatch_queue)
-{
- m_dispatch_queue_name = queue_name;
- m_queue_kind = queue_kind;
- m_queue_serial_number = queue_serial;
- m_dispatch_queue_t = dispatch_queue_t;
- m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
+void ThreadGDBRemote::SetQueueInfo(std::string &&queue_name,
+ QueueKind queue_kind, uint64_t queue_serial,
+ addr_t dispatch_queue_t,
+ LazyBool associated_with_libdispatch_queue) {
+ m_dispatch_queue_name = queue_name;
+ m_queue_kind = queue_kind;
+ m_queue_serial_number = queue_serial;
+ m_dispatch_queue_t = dispatch_queue_t;
+ m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
}
+const char *ThreadGDBRemote::GetQueueName() {
+ // If our cached queue info is valid, then someone called
+ // ThreadGDBRemote::SetQueueInfo(...)
+ // with valid information that was gleaned from the stop reply packet. In this
+ // case we trust
+ // that the info is valid in m_dispatch_queue_name without refetching it
+ if (CachedQueueInfoIsValid()) {
+ if (m_dispatch_queue_name.empty())
+ return nullptr;
+ else
+ return m_dispatch_queue_name.c_str();
+ }
+ // Always re-fetch the dispatch queue name since it can change
-const char *
-ThreadGDBRemote::GetQueueName ()
-{
- // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
- if (CachedQueueInfoIsValid())
- {
- if (m_dispatch_queue_name.empty())
- return nullptr;
- else
- return m_dispatch_queue_name.c_str();
- }
- // Always re-fetch the dispatch queue name since it can change
-
- if (m_associated_with_libdispatch_queue == eLazyBoolNo)
- return nullptr;
-
- if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- SystemRuntime *runtime = process_sp->GetSystemRuntime ();
- if (runtime)
- m_dispatch_queue_name = runtime->GetQueueNameFromThreadQAddress (m_thread_dispatch_qaddr);
- else
- m_dispatch_queue_name.clear();
-
- if (!m_dispatch_queue_name.empty())
- return m_dispatch_queue_name.c_str();
- }
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
+ return nullptr;
+
+ if (m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ if (runtime)
+ m_dispatch_queue_name =
+ runtime->GetQueueNameFromThreadQAddress(m_thread_dispatch_qaddr);
+ else
+ m_dispatch_queue_name.clear();
+
+ if (!m_dispatch_queue_name.empty())
+ return m_dispatch_queue_name.c_str();
}
- return NULL;
+ }
+ return NULL;
}
-QueueKind
-ThreadGDBRemote::GetQueueKind ()
-{
- // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
- if (CachedQueueInfoIsValid())
- {
- return m_queue_kind;
- }
+QueueKind ThreadGDBRemote::GetQueueKind() {
+ // If our cached queue info is valid, then someone called
+ // ThreadGDBRemote::SetQueueInfo(...)
+ // with valid information that was gleaned from the stop reply packet. In this
+ // case we trust
+ // that the info is valid in m_dispatch_queue_name without refetching it
+ if (CachedQueueInfoIsValid()) {
+ return m_queue_kind;
+ }
+
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
+ return eQueueKindUnknown;
- if (m_associated_with_libdispatch_queue == eLazyBoolNo)
- return eQueueKindUnknown;
-
- if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- SystemRuntime *runtime = process_sp->GetSystemRuntime ();
- if (runtime)
- m_queue_kind = runtime->GetQueueKind (m_thread_dispatch_qaddr);
- return m_queue_kind;
- }
+ if (m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ if (runtime)
+ m_queue_kind = runtime->GetQueueKind(m_thread_dispatch_qaddr);
+ return m_queue_kind;
}
- return eQueueKindUnknown;
+ }
+ return eQueueKindUnknown;
}
+queue_id_t ThreadGDBRemote::GetQueueID() {
+ // If our cached queue info is valid, then someone called
+ // ThreadGDBRemote::SetQueueInfo(...)
+ // with valid information that was gleaned from the stop reply packet. In this
+ // case we trust
+ // that the info is valid in m_dispatch_queue_name without refetching it
+ if (CachedQueueInfoIsValid())
+ return m_queue_serial_number;
-queue_id_t
-ThreadGDBRemote::GetQueueID ()
-{
- // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...)
- // with valid information that was gleaned from the stop reply packet. In this case we trust
- // that the info is valid in m_dispatch_queue_name without refetching it
- if (CachedQueueInfoIsValid())
- return m_queue_serial_number;
-
- if (m_associated_with_libdispatch_queue == eLazyBoolNo)
- return LLDB_INVALID_QUEUE_ID;
-
- if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- SystemRuntime *runtime = process_sp->GetSystemRuntime ();
- if (runtime)
- {
- return runtime->GetQueueIDFromThreadQAddress (m_thread_dispatch_qaddr);
- }
- }
- }
+ if (m_associated_with_libdispatch_queue == eLazyBoolNo)
return LLDB_INVALID_QUEUE_ID;
+
+ if (m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ if (runtime) {
+ return runtime->GetQueueIDFromThreadQAddress(m_thread_dispatch_qaddr);
+ }
+ }
+ }
+ return LLDB_INVALID_QUEUE_ID;
}
-QueueSP
-ThreadGDBRemote::GetQueue ()
-{
- queue_id_t queue_id = GetQueueID();
- QueueSP queue;
- if (queue_id != LLDB_INVALID_QUEUE_ID)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- queue = process_sp->GetQueueList().FindQueueByID (queue_id);
- }
+QueueSP ThreadGDBRemote::GetQueue() {
+ queue_id_t queue_id = GetQueueID();
+ QueueSP queue;
+ if (queue_id != LLDB_INVALID_QUEUE_ID) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ queue = process_sp->GetQueueList().FindQueueByID(queue_id);
}
- return queue;
+ }
+ return queue;
}
-addr_t
-ThreadGDBRemote::GetQueueLibdispatchQueueAddress ()
-{
- if (m_dispatch_queue_t == LLDB_INVALID_ADDRESS)
- {
- if (m_thread_dispatch_qaddr != 0 && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- SystemRuntime *runtime = process_sp->GetSystemRuntime ();
- if (runtime)
- {
- m_dispatch_queue_t = runtime->GetLibdispatchQueueAddressFromThreadQAddress (m_thread_dispatch_qaddr);
- }
- }
+addr_t ThreadGDBRemote::GetQueueLibdispatchQueueAddress() {
+ if (m_dispatch_queue_t == LLDB_INVALID_ADDRESS) {
+ if (m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ SystemRuntime *runtime = process_sp->GetSystemRuntime();
+ if (runtime) {
+ m_dispatch_queue_t =
+ runtime->GetLibdispatchQueueAddressFromThreadQAddress(
+ m_thread_dispatch_qaddr);
}
+ }
}
- return m_dispatch_queue_t;
+ }
+ return m_dispatch_queue_t;
}
-void
-ThreadGDBRemote::SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t)
-{
- m_dispatch_queue_t = dispatch_queue_t;
+void ThreadGDBRemote::SetQueueLibdispatchQueueAddress(
+ lldb::addr_t dispatch_queue_t) {
+ m_dispatch_queue_t = dispatch_queue_t;
}
-bool
-ThreadGDBRemote::ThreadHasQueueInformation () const
-{
- if (m_thread_dispatch_qaddr != 0
- && m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS
- && m_dispatch_queue_t != LLDB_INVALID_ADDRESS
- && m_queue_kind != eQueueKindUnknown
- && m_queue_serial_number != 0)
- {
- return true;
- }
- return false;
+bool ThreadGDBRemote::ThreadHasQueueInformation() const {
+ if (m_thread_dispatch_qaddr != 0 &&
+ m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS &&
+ m_dispatch_queue_t != LLDB_INVALID_ADDRESS &&
+ m_queue_kind != eQueueKindUnknown && m_queue_serial_number != 0) {
+ return true;
+ }
+ return false;
}
-LazyBool
-ThreadGDBRemote::GetAssociatedWithLibdispatchQueue ()
-{
- return m_associated_with_libdispatch_queue;
+LazyBool ThreadGDBRemote::GetAssociatedWithLibdispatchQueue() {
+ return m_associated_with_libdispatch_queue;
}
-void
-ThreadGDBRemote::SetAssociatedWithLibdispatchQueue (LazyBool associated_with_libdispatch_queue)
-{
- m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
+void ThreadGDBRemote::SetAssociatedWithLibdispatchQueue(
+ LazyBool associated_with_libdispatch_queue) {
+ m_associated_with_libdispatch_queue = associated_with_libdispatch_queue;
}
-StructuredData::ObjectSP
-ThreadGDBRemote::FetchThreadExtendedInfo ()
-{
- StructuredData::ObjectSP object_sp;
- const lldb::user_id_t tid = GetProtocolID();
- Log *log(GetLogIfAnyCategoriesSet (GDBR_LOG_THREAD));
- if (log)
- log->Printf ("Fetching extended information for thread %4.4" PRIx64, tid);
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
- object_sp = gdb_process->GetExtendedInfoForThread (tid);
- }
- return object_sp;
+StructuredData::ObjectSP ThreadGDBRemote::FetchThreadExtendedInfo() {
+ StructuredData::ObjectSP object_sp;
+ const lldb::user_id_t tid = GetProtocolID();
+ Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD));
+ if (log)
+ log->Printf("Fetching extended information for thread %4.4" PRIx64, tid);
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ ProcessGDBRemote *gdb_process =
+ static_cast<ProcessGDBRemote *>(process_sp.get());
+ object_sp = gdb_process->GetExtendedInfoForThread(tid);
+ }
+ return object_sp;
}
-void
-ThreadGDBRemote::WillResume (StateType resume_state)
-{
- int signo = GetResumeSignal();
- const lldb::user_id_t tid = GetProtocolID();
- Log *log(GetLogIfAnyCategoriesSet (GDBR_LOG_THREAD));
- if (log)
- log->Printf ("Resuming thread: %4.4" PRIx64 " with state: %s.", tid, StateAsCString(resume_state));
-
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
- switch (resume_state)
- {
- case eStateSuspended:
- case eStateStopped:
- // Don't append anything for threads that should stay stopped.
- break;
-
- case eStateRunning:
- if (gdb_process->GetUnixSignals()->SignalIsValid(signo))
- gdb_process->m_continue_C_tids.push_back(std::make_pair(tid, signo));
- else
- gdb_process->m_continue_c_tids.push_back(tid);
- break;
-
- case eStateStepping:
- if (gdb_process->GetUnixSignals()->SignalIsValid(signo))
- gdb_process->m_continue_S_tids.push_back(std::make_pair(tid, signo));
- else
- gdb_process->m_continue_s_tids.push_back(tid);
- break;
-
- default:
- break;
- }
+void ThreadGDBRemote::WillResume(StateType resume_state) {
+ int signo = GetResumeSignal();
+ const lldb::user_id_t tid = GetProtocolID();
+ Log *log(GetLogIfAnyCategoriesSet(GDBR_LOG_THREAD));
+ if (log)
+ log->Printf("Resuming thread: %4.4" PRIx64 " with state: %s.", tid,
+ StateAsCString(resume_state));
+
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ ProcessGDBRemote *gdb_process =
+ static_cast<ProcessGDBRemote *>(process_sp.get());
+ switch (resume_state) {
+ case eStateSuspended:
+ case eStateStopped:
+ // Don't append anything for threads that should stay stopped.
+ break;
+
+ case eStateRunning:
+ if (gdb_process->GetUnixSignals()->SignalIsValid(signo))
+ gdb_process->m_continue_C_tids.push_back(std::make_pair(tid, signo));
+ else
+ gdb_process->m_continue_c_tids.push_back(tid);
+ break;
+
+ case eStateStepping:
+ if (gdb_process->GetUnixSignals()->SignalIsValid(signo))
+ gdb_process->m_continue_S_tids.push_back(std::make_pair(tid, signo));
+ else
+ gdb_process->m_continue_s_tids.push_back(tid);
+ break;
+
+ default:
+ break;
}
+ }
}
-void
-ThreadGDBRemote::RefreshStateAfterStop()
-{
- // Invalidate all registers in our register context. We don't set "force" to
- // true because the stop reply packet might have had some register values
- // that were expedited and these will already be copied into the register
- // context by the time this function gets called. The GDBRemoteRegisterContext
- // class has been made smart enough to detect when it needs to invalidate
- // which registers are valid by putting hooks in the register read and
- // register supply functions where they check the process stop ID and do
- // the right thing.
- const bool force = false;
- GetRegisterContext()->InvalidateIfNeeded (force);
-}
-
-bool
-ThreadGDBRemote::ThreadIDIsValid (lldb::tid_t thread)
-{
- return thread != 0;
+void ThreadGDBRemote::RefreshStateAfterStop() {
+ // Invalidate all registers in our register context. We don't set "force" to
+ // true because the stop reply packet might have had some register values
+ // that were expedited and these will already be copied into the register
+ // context by the time this function gets called. The GDBRemoteRegisterContext
+ // class has been made smart enough to detect when it needs to invalidate
+ // which registers are valid by putting hooks in the register read and
+ // register supply functions where they check the process stop ID and do
+ // the right thing.
+ const bool force = false;
+ GetRegisterContext()->InvalidateIfNeeded(force);
}
-void
-ThreadGDBRemote::Dump(Log *log, uint32_t index)
-{
+bool ThreadGDBRemote::ThreadIDIsValid(lldb::tid_t thread) {
+ return thread != 0;
}
+void ThreadGDBRemote::Dump(Log *log, uint32_t index) {}
-bool
-ThreadGDBRemote::ShouldStop (bool &step_more)
-{
- return true;
-}
-lldb::RegisterContextSP
-ThreadGDBRemote::GetRegisterContext ()
-{
- if (m_reg_context_sp.get() == NULL)
- m_reg_context_sp = CreateRegisterContextForFrame (NULL);
- return m_reg_context_sp;
+bool ThreadGDBRemote::ShouldStop(bool &step_more) { return true; }
+lldb::RegisterContextSP ThreadGDBRemote::GetRegisterContext() {
+ if (m_reg_context_sp.get() == NULL)
+ m_reg_context_sp = CreateRegisterContextForFrame(NULL);
+ return m_reg_context_sp;
}
lldb::RegisterContextSP
-ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
-{
- lldb::RegisterContextSP reg_ctx_sp;
- uint32_t concrete_frame_idx = 0;
-
- if (frame)
- concrete_frame_idx = frame->GetConcreteFrameIndex ();
-
-
- if (concrete_frame_idx == 0)
- {
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- {
- ProcessGDBRemote *gdb_process = static_cast<ProcessGDBRemote *>(process_sp.get());
- // read_all_registers_at_once will be true if 'p' packet is not supported.
- bool read_all_registers_at_once = !gdb_process->GetGDBRemote().GetpPacketSupported (GetID());
- reg_ctx_sp.reset (new GDBRemoteRegisterContext (*this, concrete_frame_idx, gdb_process->m_register_info, read_all_registers_at_once));
- }
- }
- else
- {
- Unwind *unwinder = GetUnwinder ();
- if (unwinder)
- reg_ctx_sp = unwinder->CreateRegisterContextForFrame (frame);
+ThreadGDBRemote::CreateRegisterContextForFrame(StackFrame *frame) {
+ lldb::RegisterContextSP reg_ctx_sp;
+ uint32_t concrete_frame_idx = 0;
+
+ if (frame)
+ concrete_frame_idx = frame->GetConcreteFrameIndex();
+
+ if (concrete_frame_idx == 0) {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp) {
+ ProcessGDBRemote *gdb_process =
+ static_cast<ProcessGDBRemote *>(process_sp.get());
+ // read_all_registers_at_once will be true if 'p' packet is not supported.
+ bool read_all_registers_at_once =
+ !gdb_process->GetGDBRemote().GetpPacketSupported(GetID());
+ reg_ctx_sp.reset(new GDBRemoteRegisterContext(
+ *this, concrete_frame_idx, gdb_process->m_register_info,
+ read_all_registers_at_once));
}
- return reg_ctx_sp;
+ } else {
+ Unwind *unwinder = GetUnwinder();
+ if (unwinder)
+ reg_ctx_sp = unwinder->CreateRegisterContextForFrame(frame);
+ }
+ return reg_ctx_sp;
}
-bool
-ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
-{
- GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
- assert (gdb_reg_ctx);
- return gdb_reg_ctx->PrivateSetRegisterValue (reg, response);
+bool ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg,
+ llvm::ArrayRef<uint8_t> data) {
+ GDBRemoteRegisterContext *gdb_reg_ctx =
+ static_cast<GDBRemoteRegisterContext *>(GetRegisterContext().get());
+ assert(gdb_reg_ctx);
+ return gdb_reg_ctx->PrivateSetRegisterValue(reg, data);
}
-bool
-ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, uint64_t regval)
-{
- GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
- assert (gdb_reg_ctx);
- return gdb_reg_ctx->PrivateSetRegisterValue (reg, regval);
+bool ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg, uint64_t regval) {
+ GDBRemoteRegisterContext *gdb_reg_ctx =
+ static_cast<GDBRemoteRegisterContext *>(GetRegisterContext().get());
+ assert(gdb_reg_ctx);
+ return gdb_reg_ctx->PrivateSetRegisterValue(reg, regval);
}
-bool
-ThreadGDBRemote::CalculateStopInfo ()
-{
- ProcessSP process_sp (GetProcess());
- if (process_sp)
- return static_cast<ProcessGDBRemote *>(process_sp.get())->CalculateThreadStopInfo(this);
- return false;
+bool ThreadGDBRemote::CalculateStopInfo() {
+ ProcessSP process_sp(GetProcess());
+ if (process_sp)
+ return static_cast<ProcessGDBRemote *>(process_sp.get())
+ ->CalculateThreadStopInfo(this);
+ return false;
}
-
-
diff --git a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index d7619f4..27caf42 100644
--- a/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/contrib/llvm/tools/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -27,126 +27,94 @@ namespace process_gdb_remote {
class ProcessGDBRemote;
-class ThreadGDBRemote : public Thread
-{
+class ThreadGDBRemote : public Thread {
public:
- ThreadGDBRemote (Process &process, lldb::tid_t tid);
+ ThreadGDBRemote(Process &process, lldb::tid_t tid);
- ~ThreadGDBRemote() override;
+ ~ThreadGDBRemote() override;
- void
- WillResume (lldb::StateType resume_state) override;
+ void WillResume(lldb::StateType resume_state) override;
- void
- RefreshStateAfterStop() override;
+ void RefreshStateAfterStop() override;
- const char *
- GetName () override;
+ const char *GetName() override;
- const char *
- GetQueueName () override;
+ const char *GetQueueName() override;
- lldb::QueueKind
- GetQueueKind () override;
+ lldb::QueueKind GetQueueKind() override;
- lldb::queue_id_t
- GetQueueID () override;
+ lldb::queue_id_t GetQueueID() override;
- lldb::QueueSP
- GetQueue () override;
+ lldb::QueueSP GetQueue() override;
- lldb::addr_t
- GetQueueLibdispatchQueueAddress () override;
+ lldb::addr_t GetQueueLibdispatchQueueAddress() override;
- void
- SetQueueLibdispatchQueueAddress (lldb::addr_t dispatch_queue_t) override;
+ void SetQueueLibdispatchQueueAddress(lldb::addr_t dispatch_queue_t) override;
- bool
- ThreadHasQueueInformation () const override;
+ bool ThreadHasQueueInformation() const override;
- lldb::RegisterContextSP
- GetRegisterContext () override;
+ lldb::RegisterContextSP GetRegisterContext() override;
- lldb::RegisterContextSP
- CreateRegisterContextForFrame (StackFrame *frame) override;
+ lldb::RegisterContextSP
+ CreateRegisterContextForFrame(StackFrame *frame) override;
- void
- Dump (Log *log, uint32_t index);
+ void Dump(Log *log, uint32_t index);
- static bool
- ThreadIDIsValid (lldb::tid_t thread);
+ static bool ThreadIDIsValid(lldb::tid_t thread);
- bool
- ShouldStop (bool &step_more);
+ bool ShouldStop(bool &step_more);
- const char *
- GetBasicInfoAsString ();
+ const char *GetBasicInfoAsString();
- void
- SetName (const char *name) override
- {
- if (name && name[0])
- m_thread_name.assign (name);
- else
- m_thread_name.clear();
- }
+ void SetName(const char *name) override {
+ if (name && name[0])
+ m_thread_name.assign(name);
+ else
+ m_thread_name.clear();
+ }
- lldb::addr_t
- GetThreadDispatchQAddr ()
- {
- return m_thread_dispatch_qaddr;
- }
+ lldb::addr_t GetThreadDispatchQAddr() { return m_thread_dispatch_qaddr; }
- void
- SetThreadDispatchQAddr (lldb::addr_t thread_dispatch_qaddr)
- {
- m_thread_dispatch_qaddr = thread_dispatch_qaddr;
- }
+ void SetThreadDispatchQAddr(lldb::addr_t thread_dispatch_qaddr) {
+ m_thread_dispatch_qaddr = thread_dispatch_qaddr;
+ }
- void
- ClearQueueInfo ();
-
- void
- SetQueueInfo (std::string &&queue_name, lldb::QueueKind queue_kind, uint64_t queue_serial, lldb::addr_t dispatch_queue_t, lldb_private::LazyBool associated_with_libdispatch_queue);
+ void ClearQueueInfo();
- lldb_private::LazyBool
- GetAssociatedWithLibdispatchQueue () override;
+ void SetQueueInfo(std::string &&queue_name, lldb::QueueKind queue_kind,
+ uint64_t queue_serial, lldb::addr_t dispatch_queue_t,
+ lldb_private::LazyBool associated_with_libdispatch_queue);
- void
- SetAssociatedWithLibdispatchQueue (lldb_private::LazyBool associated_with_libdispatch_queue) override;
+ lldb_private::LazyBool GetAssociatedWithLibdispatchQueue() override;
- StructuredData::ObjectSP
- FetchThreadExtendedInfo () override;
+ void SetAssociatedWithLibdispatchQueue(
+ lldb_private::LazyBool associated_with_libdispatch_queue) override;
+
+ StructuredData::ObjectSP FetchThreadExtendedInfo() override;
protected:
- friend class ProcessGDBRemote;
-
- std::string m_thread_name;
- std::string m_dispatch_queue_name;
- lldb::addr_t m_thread_dispatch_qaddr;
- lldb::addr_t m_dispatch_queue_t;
- lldb::QueueKind m_queue_kind; // Queue info from stop reply/stop info for thread
- uint64_t m_queue_serial_number; // Queue info from stop reply/stop info for thread
- lldb_private::LazyBool m_associated_with_libdispatch_queue;
-
- bool
- PrivateSetRegisterValue (uint32_t reg,
- StringExtractor &response);
-
- bool
- PrivateSetRegisterValue (uint32_t reg,
- uint64_t regval);
-
- bool
- CachedQueueInfoIsValid() const
- {
- return m_queue_kind != lldb::eQueueKindUnknown;
- }
- void
- SetStopInfoFromPacket (StringExtractor &stop_packet, uint32_t stop_id);
-
- bool
- CalculateStopInfo () override;
+ friend class ProcessGDBRemote;
+
+ std::string m_thread_name;
+ std::string m_dispatch_queue_name;
+ lldb::addr_t m_thread_dispatch_qaddr;
+ lldb::addr_t m_dispatch_queue_t;
+ lldb::QueueKind
+ m_queue_kind; // Queue info from stop reply/stop info for thread
+ uint64_t
+ m_queue_serial_number; // Queue info from stop reply/stop info for thread
+ lldb_private::LazyBool m_associated_with_libdispatch_queue;
+
+ bool PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data);
+
+ bool PrivateSetRegisterValue(uint32_t reg, uint64_t regval);
+
+ bool CachedQueueInfoIsValid() const {
+ return m_queue_kind != lldb::eQueueKindUnknown;
+ }
+ void SetStopInfoFromPacket(StringExtractor &stop_packet, uint32_t stop_id);
+
+ bool CalculateStopInfo() override;
};
} // namespace process_gdb_remote
OpenPOWER on IntegriCloud