[Lldb-commits] [lldb] r208051 - Add a simple qSupported packet, fix a bug in decode_binary_data(),

Jason Molenda jmolenda at apple.com
Mon May 5 19:53:43 PDT 2014


Author: jmolenda
Date: Mon May  5 21:53:43 2014
New Revision: 208051

URL: http://llvm.org/viewvc/llvm-project?rev=208051&view=rev
Log:
Add a simple qSupported packet, fix a bug in decode_binary_data(), 
add a new 'x' packet for reading data in binary format.  Document
the 'x' packet.  
<rdar://problem/16032150> 

Modified:
    lldb/trunk/docs/lldb-gdb-remote.txt
    lldb/trunk/tools/debugserver/source/RNBRemote.cpp
    lldb/trunk/tools/debugserver/source/RNBRemote.h

Modified: lldb/trunk/docs/lldb-gdb-remote.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/docs/lldb-gdb-remote.txt?rev=208051&r1=208050&r2=208051&view=diff
==============================================================================
--- lldb/trunk/docs/lldb-gdb-remote.txt (original)
+++ lldb/trunk/docs/lldb-gdb-remote.txt Mon May  5 21:53:43 2014
@@ -837,6 +837,40 @@ The lack of 'permissions:' indicates tha
 for this region.
 
 //----------------------------------------------------------------------
+// 'x' - Binary memory read
+//
+// Like the 'm' (read) and 'M' (write) packets, this is a partner to the
+// 'X' (write binary data) packet, 'x'.
+//
+// It is called like
+//
+// xADDRESS,LENGTH
+//
+// where both ADDRESS and LENGTH are big-endian base 16 values.
+//
+// To test if this packet is available, send a addr/len of 0:
+//
+// x0,0
+//
+// and you will get an "OK" response.
+//
+// The reply will be the data requested in 8-bit binary data format.
+// The standard quoting is applied to the payload -- characters
+//   }  #  $  *
+// will all be escaped with '}' (0x7d) character and then XOR'ed with 0x20.
+//
+// A typical use to read 512 bytes at 0x1000 would look like
+//
+// x0x1000,0x200
+//
+// The "0x" prefixes are optional - like most of the gdb-remote packets,
+// omitting them will work fine; these numbers are always base 16.
+// 
+// The length of the payload is not provided.  A reliable, 8-bit clean, 
+// transport layer is assumed.
+//----------------------------------------------------------------------
+
+//----------------------------------------------------------------------
 // Detach and stay stopped:
 //
 // We extended the "D" packet to specify that the monitor should keep the

Modified: lldb/trunk/tools/debugserver/source/RNBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBRemote.cpp?rev=208051&r1=208050&r2=208051&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBRemote.cpp (original)
+++ lldb/trunk/tools/debugserver/source/RNBRemote.cpp Mon May  5 21:53:43 2014
@@ -136,14 +136,15 @@ RNBRemote::CreatePacketTable  ()
 //  t.push_back (Packet (restart,                       &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "R", "Restart inferior"));
 //  t.push_back (Packet (search_mem_backwards,          &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "t", "Search memory backwards"));
     t.push_back (Packet (thread_alive_p,                &RNBRemote::HandlePacket_T,             NULL, "T", "Is thread alive"));
+    t.push_back (Packet (query_supported_features,      &RNBRemote::HandlePacket_qSupported,    NULL, "qSupported", "Query about supported features"));
     t.push_back (Packet (vattach,                       &RNBRemote::HandlePacket_v,             NULL, "vAttach", "Attach to a new process"));
     t.push_back (Packet (vattachwait,                   &RNBRemote::HandlePacket_v,             NULL, "vAttachWait", "Wait for a process to start up then attach to it"));
     t.push_back (Packet (vattachorwait,                 &RNBRemote::HandlePacket_v,             NULL, "vAttachOrWait", "Attach to the process or if it doesn't exist, wait for the process to start up then attach to it"));
     t.push_back (Packet (vattachname,                   &RNBRemote::HandlePacket_v,             NULL, "vAttachName", "Attach to an existing process by name"));
     t.push_back (Packet (vcont_list_actions,            &RNBRemote::HandlePacket_v,             NULL, "vCont;", "Verbose resume with thread actions"));
     t.push_back (Packet (vcont_list_actions,            &RNBRemote::HandlePacket_v,             NULL, "vCont?", "List valid continue-with-thread-actions actions"));
-    // The X packet doesn't currently work. If/when it does, remove the line above and uncomment out the line below
-//  t.push_back (Packet (write_data_to_memory,          &RNBRemote::HandlePacket_X,             NULL, "X", "Write data to memory"));
+  t.push_back (Packet (read_data_from_memory,           &RNBRemote::HandlePacket_x,             NULL, "x", "Read data from memory"));
+  t.push_back (Packet (write_data_to_memory,            &RNBRemote::HandlePacket_X,             NULL, "X", "Write data to memory"));
 //  t.push_back (Packet (insert_hardware_bp,            &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "Z1", "Insert hardware breakpoint"));
 //  t.push_back (Packet (remove_hardware_bp,            &RNBRemote::HandlePacket_UNIMPLEMENTED, NULL, "z1", "Remove hardware breakpoint"));
     t.push_back (Packet (insert_write_watch_bp,         &RNBRemote::HandlePacket_z,             NULL, "Z2", "Insert write watchpoint"));
@@ -817,10 +818,10 @@ best_guess_cpu_type ()
 
 /* Read the bytes in STR which are GDB Remote Protocol binary encoded bytes
  (8-bit bytes).
- This encoding uses 0x7d ('}') as an escape character for 0x7d ('}'),
- 0x23 ('#'), and 0x24 ('$').
+ This encoding uses 0x7d ('}') as an escape character for 
+ 0x7d ('}'), 0x23 ('#'), 0x24 ('$'), 0x2a ('*').
  LEN is the number of bytes to be processed.  If a character is escaped,
- it is 2 characters for LEN.  A LEN of -1 means encode-until-nul-byte
+ it is 2 characters for LEN.  A LEN of -1 means decode-until-nul-byte
  (end of string).  */
 
 std::vector<uint8_t>
@@ -841,7 +842,7 @@ decode_binary_data (const char *str, siz
         {
             len--;
             str++;
-            c ^= 0x20;
+            c = *str ^ 0x20;
         }
         bytes.push_back (c);
     }
@@ -2537,6 +2538,89 @@ RNBRemote::HandlePacket_m (const char *p
     return SendPacket (ostrm.str ());
 }
 
+// Read memory, sent it up as binary data.
+// Usage:  xADDR,LEN
+// ADDR and LEN are both base 16.
+
+// Responds with 'OK' for zero-length request
+// or 
+//
+// DATA
+//
+// where DATA is the binary data payload.
+
+rnb_err_t
+RNBRemote::HandlePacket_x (const char *p)
+{
+    if (p == NULL || p[0] == '\0' || strlen (p) < 3)
+    {
+        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Too short X packet");
+    }
+
+    char *c;
+    p++;
+    errno = 0;
+    nub_addr_t addr = strtoull (p, &c, 16);
+    if (errno != 0)
+    {
+        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid address in X packet");
+    }
+    if (*c != ',')
+    {
+        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
+    }
+
+    /* Advance 'p' to the number of bytes to be read.  */
+    p += (c - p) + 1;
+
+    errno = 0;
+    int length = strtoul (p, NULL, 16);
+    if (errno != 0)
+    {
+        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in x packet");
+    }
+
+    // zero length read means this is a test of whether that packet is implemented or not.
+    if (length == 0)
+    {
+        return SendPacket ("OK");
+    }
+
+    std::vector<uint8_t> buf (length);
+
+    if (buf.capacity() != length)
+    {
+        return SendPacket ("E79");
+    }
+    int bytes_read = DNBProcessMemoryRead (m_ctx.ProcessID(), addr, buf.size(), &buf[0]);
+    if (bytes_read == 0)
+    {
+        return SendPacket ("E80");
+    }
+
+    std::vector<uint8_t> buf_quoted;
+    buf_quoted.reserve (bytes_read + 30);
+    for (int i = 0; i < bytes_read; i++)
+    {
+        if (buf[i] == '#' || buf[i] == '$' || buf[i] == '}' || buf[i] == '*')
+        {
+            buf_quoted.push_back(0x7d);
+            buf_quoted.push_back(buf[i] ^ 0x20);
+        }
+        else
+        {
+            buf_quoted.push_back(buf[i]);
+        }
+    }
+    length = buf_quoted.size();
+
+    std::ostringstream ostrm;
+    for (int i = 0; i < length; i++)
+        ostrm << buf_quoted[i];
+
+    return SendPacket (ostrm.str ());
+}
+
 rnb_err_t
 RNBRemote::HandlePacket_X (const char *p)
 {
@@ -2558,14 +2642,16 @@ RNBRemote::HandlePacket_X (const char *p
         return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Comma sep missing in X packet");
     }
 
-    /* Advance 'p' to the length part of the packet.  */
+    /* Advance 'p' to the length part of the packet.  NB this is the length of the packet
+       including any escaped chars.  The data payload may be a little bit smaller after
+       decoding.  */
     p += (c - p) + 1;
 
     errno = 0;
     int length = strtoul (p, NULL, 16);
     if (errno != 0 && length == 0)
     {
-        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in m packet");
+        return HandlePacket_ILLFORMED (__FILE__, __LINE__, p, "Invalid length in X packet");
     }
 
     // I think gdb sends a zero length write request to test whether this
@@ -2882,6 +2968,15 @@ GetProcessNameFrom_vAttach (const char *
     return return_val;
 }
 
+rnb_err_t
+RNBRemote::HandlePacket_qSupported (const char *p)
+{
+    uint32_t max_packet_size = 128 * 1024;  // 128KBytes is a reasonable max packet size--debugger can always use less
+    char buf[64];
+    snprintf (buf, sizeof(buf), "PacketSize=%x", max_packet_size);
+    return SendPacket (buf);
+}
+
 /*
  vAttach;pid
 

Modified: lldb/trunk/tools/debugserver/source/RNBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/tools/debugserver/source/RNBRemote.h?rev=208051&r1=208050&r2=208051&view=diff
==============================================================================
--- lldb/trunk/tools/debugserver/source/RNBRemote.h (original)
+++ lldb/trunk/tools/debugserver/source/RNBRemote.h Mon May  5 21:53:43 2014
@@ -67,6 +67,7 @@ public:
         vattachname,                    // 'vAttachName:XX...' where XX is one or more hex encoded process name ASCII bytes
         vcont,                          // 'vCont'
         vcont_list_actions,             // 'vCont?'
+        read_data_from_memory,          // 'x'
         write_data_to_memory,           // 'X'
         insert_mem_bp,                  // 'Z0'
         remove_mem_bp,                  // 'z0'
@@ -92,6 +93,7 @@ public:
         query_register_info,            // 'qRegisterInfo'
         query_shlib_notify_info_addr,   // 'qShlibInfoAddr'
         query_step_packet_supported,    // 'qStepPacketSupported'
+        query_supported_features,       // 'qSupported'
         query_vattachorwait_supported,  // 'qVAttachOrWaitSupported'
         query_sync_thread_state_supported,// 'QSyncThreadState'
         query_host_info,                // 'qHostInfo'
@@ -202,6 +204,7 @@ public:
     rnb_err_t HandlePacket_last_signal (const char *p);
     rnb_err_t HandlePacket_m (const char *p);
     rnb_err_t HandlePacket_M (const char *p);
+    rnb_err_t HandlePacket_x (const char *p);
     rnb_err_t HandlePacket_X (const char *p);
     rnb_err_t HandlePacket_g (const char *p);
     rnb_err_t HandlePacket_G (const char *p);
@@ -215,6 +218,7 @@ public:
     rnb_err_t HandlePacket_k (const char *p);
     rnb_err_t HandlePacket_s (const char *p);
     rnb_err_t HandlePacket_S (const char *p);
+    rnb_err_t HandlePacket_qSupported (const char *p);
     rnb_err_t HandlePacket_v (const char *p);
     rnb_err_t HandlePacket_UNIMPLEMENTED (const char *p);
     rnb_err_t HandlePacket_ILLFORMED (const char *file, int line, const char *p, const char *description);





More information about the lldb-commits mailing list