diff options
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp')
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp | 136 |
1 files changed, 135 insertions, 1 deletions
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) { |