summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Plugins/Process')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp36
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h10
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp136
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h51
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp23
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h7
6 files changed, 261 insertions, 2 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
index 786d80176c6..fde38037d9a 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.cpp
@@ -11,6 +11,7 @@
#include "llvm/ADT/StringExtras.h"
+#include "lldb/Target/Process.h"
#include "lldb/Target/UnixSignals.h"
#include "lldb/Utility/LLDBAssert.h"
@@ -100,6 +101,41 @@ GDBRemoteClientBase::SendContinuePacketAndWaitForResponse(ContinueDelegate &dele
case 'A':
delegate.HandleAsyncMisc(llvm::StringRef(response.GetStringRef()).substr(1));
break;
+
+ case 'J':
+ // Asynchronous JSON packet, destined for a
+ // StructuredDataPlugin.
+ {
+ // Parse the content into a StructuredData instance.
+ auto payload_index = strlen("JSON-async:");
+ StructuredData::ObjectSP json_sp =
+ StructuredData::ParseJSON(response.GetStringRef()
+ .substr(payload_index));
+ if (log)
+ {
+ if (json_sp)
+ log->Printf(
+ "GDBRemoteCommmunicationClientBase::%s() "
+ "received Async StructuredData packet: %s",
+ __FUNCTION__,
+ response.GetStringRef().
+ substr(payload_index).c_str());
+ else
+ log->Printf("GDBRemoteCommmunicationClientBase::%s"
+ "() received StructuredData packet:"
+ " parse failure", __FUNCTION__);
+ }
+
+ // Pass the data to the process to route to the
+ // appropriate plugin. The plugin controls what happens
+ // to it from there.
+ bool routed = delegate.HandleAsyncStructuredData(json_sp);
+ if (log)
+ log->Printf("GDBRemoteCommmunicationClientBase::%s()"
+ " packet %s", __FUNCTION__,
+ routed ? "handled" : "not handled");
+ break;
+ }
case 'T':
case 'S':
// Do this with the continue lock held.
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
index 9cfba4b8394..684ef3e80d1 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteClientBase.h
@@ -31,6 +31,16 @@ public:
HandleAsyncMisc(llvm::StringRef data) = 0;
virtual void
HandleStopReply() = 0;
+
+ //
+ /// Processes async structured data.
+ ///
+ /// @return
+ /// true if the data was handled; otherwise, false.
+ //
+ virtual bool
+ HandleAsyncStructuredData(const StructuredData::ObjectSP
+ &object_sp) = 0;
};
GDBRemoteClientBase(const char *comm_name, const char *listener_name);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 00357dd54e3..d893b868e75 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -30,6 +30,8 @@
#include "lldb/Interpreter/Args.h"
#include "lldb/Symbol/Symbol.h"
#include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Target/UnixSignals.h"
+#include "lldb/Utility/LLDBAssert.h"
#include "lldb/Target/Target.h"
// Project includes
@@ -114,7 +116,10 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_gdb_server_name(),
m_gdb_server_version(UINT32_MAX),
m_default_packet_timeout(0),
- m_max_packet_size(0)
+ m_max_packet_size(0),
+ m_qSupported_response(),
+ m_supported_async_json_packets_is_valid(false),
+ m_supported_async_json_packets_sp()
{
}
@@ -378,6 +383,9 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings (bool did_exec)
m_gdb_server_version = UINT32_MAX;
m_default_packet_timeout = 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();
}
// These flags should be reset when we first connect to a GDB server
@@ -413,6 +421,12 @@ GDBRemoteCommunicationClient::GetRemoteQSupported ()
/*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+"))
@@ -3906,6 +3920,126 @@ GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process)
}
}
+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_is_valid)
+ {
+ StreamString stream;
+ m_supported_async_json_packets_sp->Dump(stream);
+ log->Printf("GDBRemoteCommunicationClient::%s(): supported async "
+ "JSON packets: %s", __FUNCTION__,
+ stream.GetString().c_str());
+ }
+ }
+
+ 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.GetData(),
+ unescaped_stream.GetSize());
+ }
+ stream.Flush();
+
+ // Send the packet.
+ const bool send_async = false;
+ StringExtractorGDBRemote response;
+ auto result = SendPacketAndWaitForResponse(stream.GetString().c_str(),
+ 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(),
+ result);
+ }
+ return error;
+}
+
void
GDBRemoteCommunicationClient::OnRunPacketSent(bool first)
{
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index b041ecbf3da..54e70792175 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -547,6 +547,53 @@ public:
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;
@@ -617,6 +664,10 @@ protected:
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
+ 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);
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index 1fa78fe155f..be5c3b552c8 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1175,7 +1175,7 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
{
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
if (log)
- log->Printf ("ProcessGDBRemote::DidLaunch()");
+ log->Printf ("ProcessGDBRemote::%s()", __FUNCTION__);
if (GetID() != LLDB_INVALID_PROCESS_ID)
{
BuildDynamicRegisterInfo (false);
@@ -1271,6 +1271,13 @@ ProcessGDBRemote::DidLaunchOrAttach (ArchSpec& process_arch)
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);
}
}
@@ -4342,6 +4349,13 @@ ProcessGDBRemote::GetSharedCacheInfo ()
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.
// If the remote stub has a max packet size, stay under that size.
@@ -5235,6 +5249,13 @@ ProcessGDBRemote::HandleStopReply()
BuildDynamicRegisterInfo(true);
}
+bool
+ProcessGDBRemote::HandleAsyncStructuredData(const StructuredData::ObjectSP
+ &object_sp)
+{
+ return RouteAsyncStructuredData(object_sp);
+}
+
class CommandObjectProcessGDBRemoteSpeedTest: public CommandObjectParsed
{
public:
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
index 0f41a2149ea..3a0dd2f7235 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -261,6 +261,10 @@ public:
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;
@@ -506,6 +510,9 @@ private:
HandleAsyncMisc(llvm::StringRef data) override;
void
HandleStopReply() override;
+ bool
+ HandleAsyncStructuredData(const StructuredData::ObjectSP
+ &object_sp) override;
DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote);
};
OpenPOWER on IntegriCloud