summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
diff options
context:
space:
mode:
authorJason Molenda <jmolenda@apple.com>2015-06-18 21:46:06 +0000
committerJason Molenda <jmolenda@apple.com>2015-06-18 21:46:06 +0000
commit91ffe0a5701d310433abf3865651ae122932e8c8 (patch)
tree4bf0213d496acd43c566d25cb2061c394cb80052 /lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
parent905c802f5ba5322ee1df53c410ab9f1a14c028fc (diff)
downloadbcm5719-llvm-91ffe0a5701d310433abf3865651ae122932e8c8.tar.gz
bcm5719-llvm-91ffe0a5701d310433abf3865651ae122932e8c8.zip
Add a new wart, I mean feature, on to gdb-remote protocol: compression.
For some communication channels, sending large packets can be very slow. In those cases, it may be faster to compress the contents of the packet on the target device and decompress it on the debug host system. For instance, communicating with a device using something like Bluetooth may be an environment where this tradeoff is a good one. This patch adds a new field to the response to the "qSupported" packet (which returns a "qXfer:features:" response) -- SupportedCompressions and DefaultCompressionMinSize. These tell you what the remote stub can support. lldb, if it wants to enable compression and can handle one of those algorithms, it can send a QEnableCompression packet specifying the algorithm and optionally the minimum packet size to use compression on. lldb may have better knowledge about the best tradeoff for a given communication channel. I added support to debugserver an lldb to use the zlib APIs (if -DHAVE_LIBZ=1 is in CFLAGS and -lz is in LDFLAGS) and the libcompression APIs on Mac OS X 10.11 and later (if -DHAVE_LIBCOMPRESSION=1). libz "zlib-deflate" compression. libcompression can support deflate, lz4, lzma, and a proprietary lzfse algorithm. libcompression has been hand-tuned for Apple hardware so it should be preferred if available. debugserver currently only adds the SupportedCompressions when it is being run on an Apple watch (TARGET_OS_WATCH). Comment that #if out from RNBRemote.cpp if you want to enable it to see how it works. I haven't tested this on a native system configuration but surely it will be slower to compress & decompress the packets in a same-system debug session. I haven't had a chance to add support for this to GDBRemoteCommunciationServer.cpp yet. <rdar://problem/21090180> llvm-svn: 240066
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp156
1 files changed, 156 insertions, 0 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index 21a538ced17..d2a15b3152e 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -43,6 +43,10 @@
#include "ProcessGDBRemoteLog.h"
#include "lldb/Host/Config.h"
+#if defined (HAVE_LIBCOMPRESSION)
+#include <compression.h>
+#endif
+
using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::process_gdb_remote;
@@ -423,6 +427,59 @@ GDBRemoteCommunicationClient::GetRemoteQSupported ()
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
@@ -1629,6 +1686,105 @@ GDBRemoteCommunicationClient::GetGDBServerVersion()
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;
+ }
+ }
+ }
+#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;
+ }
+ }
+ }
+#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;
+ }
+ }
+ }
+#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;
+ }
+ }
+ }
+#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;
+ }
+ }
+}
+
const char *
GDBRemoteCommunicationClient::GetGDBServerProgramName()
{
OpenPOWER on IntegriCloud