diff --git a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
index d7efdf2..d4a8138 100644
--- a/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
+++ b/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp
@@ -206,7 +206,35 @@ GDBRemoteCommunication::SendPacketNoLock (const char *payload, size_t payload_le
         StreamString packet(0, 4, eByteOrderBig);
 
         packet.PutChar('$');
-        packet.Write (payload, payload_length);
+
+        // Escape characters, while still trying to optimize usual case: non-escaped
+        // character are batched in as few writes as possible, and escaped characters
+        // are expected to be rare
+        for (const char* pos = payload, *end = payload + payload_length; pos < end; ++pos)
+        {
+            // The bytes 0x23 (ascii ‘#’), 0x24 (ascii ‘$’), and 0x7d (ascii ‘}’)
+            // must always be escaped.
+            bool escaped_character = false;
+
+            // Try to find the next batch (until next character to escape)
+            const char* start_range = pos;
+            for (; pos < end; ++pos)
+            {
+                char c = *pos;
+                if (c == '#' || c == '$' || c == '}')
+                {
+                    escaped_character = true;
+                    break;
+                }
+            }
+			if (pos > start_range)
+				packet.Write(start_range, pos - start_range);
+            if (escaped_character)
+            {
+                packet.PutChar('}');
+                packet.PutChar(*pos ^ 0x20);
+            }
+        }
         packet.PutChar('#');
         packet.PutHex8(CalculcateChecksum (payload, payload_length));
 
@@ -461,8 +489,34 @@ GDBRemoteCommunication::CheckForPacket (const uint8_t *src, size_t src_len, Stri
 
             m_history.AddPacket (m_bytes.c_str(), total_length, History::ePacketTypeRecv, total_length);
 
-            packet_str.assign (m_bytes, content_start, content_length);
-            
+            // Use runtime-length encoding to decode packet data
+            // Let's 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_start + content_length; ++c)
+            {
+                if (*c == '}')
+                {
+                    // Escape pattern:
+                    // XOR next character with 0x20
+                    packet_str.push_back(*++c ^ 0x20);
+                }
+                else if (*c == '*')
+                {
+                    // Runtime-length encoding repeat pattern:
+                    // previous character gets repeated
+					char previousChar = packet_str.back();
+                    // Number of time the previous character is repeated
+                    int count = *++c + 3 - ' ';
+                    // Add the character 
+                    for (int i = 0; i < count; ++i)
+                        packet_str.push_back(previousChar);
+                }
+                else
+                {
+                    packet_str.push_back(*c);
+                }
+            }
+
             if (m_bytes[0] == '$')
             {
                 assert (checksum_idx < m_bytes.size());
