[Lldb-commits] [lldb] r151939 - in /lldb/trunk/source: Core/RegisterValue.cpp Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h

Johnny Chen johnny.chen at apple.com
Fri Mar 2 13:32:51 PST 2012


Author: johnny
Date: Fri Mar  2 15:32:50 2012
New Revision: 151939

URL: http://llvm.org/viewvc/llvm-project?rev=151939&view=rev
Log:
rdar://problem/10652076

Add logic to GDBRemoteRegisterContext class to be able to read/write a "composite" register
which has "primordial" registers as its constituents.  In particular, Read/WriteRegisterBytes()
now delegate to Get/SetPrimordialRegister() helper methods to read/write register contents.

Also modify RegisterValue class to be able to parse "register write" string value for the
NEON quadword registers which is displayed as a vector of uint8's.

Example:

(lldb) register write q0 "{0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10}"
(lldb) register read q0
q0 = {0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10}
(lldb) register read --format uint8_t[] s0
s0 = {0x01 0x02 0x03 0x04}
(lldb) register read --format uint8_t[] d0
d0 = {0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08}
(lldb) register read --format uint8_t[] d1
d1 = {0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10}

Modified:
    lldb/trunk/source/Core/RegisterValue.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h

Modified: lldb/trunk/source/Core/RegisterValue.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Core/RegisterValue.cpp?rev=151939&r1=151938&r2=151939&view=diff
==============================================================================
--- lldb/trunk/source/Core/RegisterValue.cpp (original)
+++ lldb/trunk/source/Core/RegisterValue.cpp Fri Mar  2 15:32:50 2012
@@ -363,6 +363,58 @@
     return error;
 }
 
+#include "llvm/ADT/StringRef.h"
+#include <vector>
+static inline void StripSpaces(llvm::StringRef &Str)
+{
+    while (!Str.empty() && isspace(Str[0]))
+        Str = Str.substr(1);
+    while (!Str.empty() && isspace(Str.back()))
+        Str = Str.substr(0, Str.size()-1);
+}
+static inline void LStrip(llvm::StringRef &Str, char c)
+{
+    if (!Str.empty() && Str.front() == c)
+        Str = Str.substr(1);
+}
+static inline void RStrip(llvm::StringRef &Str, char c)
+{
+    if (!Str.empty() && Str.back() == c)
+        Str = Str.substr(0, Str.size()-1);
+}
+// Helper function for RegisterValue::SetValueFromCString()
+static bool
+ParseVectorEncoding(const RegisterInfo *reg_info, const char *vector_str, const uint32_t byte_size, RegisterValue *reg_value)
+{
+    // Example: vector_str = "{0x2c 0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f 0x2a 0x3e}".
+    llvm::StringRef Str(vector_str);
+    StripSpaces(Str);
+    LStrip(Str, '{');
+    RStrip(Str, '}');
+    StripSpaces(Str);
+
+    char Sep = ' ';
+
+    // The first split should give us:
+    // ('0x2c', '0x4b 0x2a 0x3e 0xd0 0x4f 0x2a 0x3e 0xac 0x4a 0x2a 0x3e 0x84 0x4f 0x2a 0x3e').
+    std::pair<llvm::StringRef, llvm::StringRef> Pair = Str.split(Sep);
+    std::vector<uint8_t> bytes;
+    unsigned byte = 0;
+
+    // Using radix auto-sensing by passing 0 as the radix.
+    // Keep on processing the vector elements as long as the parsing succeeds and the vector size is < byte_size.
+    while (!Pair.first.getAsInteger(0, byte) && bytes.size() < byte_size) {
+        bytes.push_back(byte);
+        Pair = Pair.second.split(Sep);
+    }
+
+    // Check for vector of exact byte_size elements.
+    if (bytes.size() != byte_size)
+        return false;
+
+    reg_value->SetBytes(&(bytes.front()), byte_size, eByteOrderLittle);
+    return true;
+}
 Error
 RegisterValue::SetValueFromCString (const RegisterInfo *reg_info, const char *value_str)
 {
@@ -459,7 +511,8 @@
             break;
             
         case eEncodingVector:
-            error.SetErrorString ("vector encoding unsupported.");
+            if (!ParseVectorEncoding(reg_info, value_str, byte_size, this))
+                error.SetErrorString ("unrecognized vector encoding string value.");
             break;
     }
     if (error.Fail())

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp?rev=151939&r1=151938&r2=151939&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp Fri Mar  2 15:32:50 2012
@@ -143,7 +143,25 @@
     return success;
 }
 
+// Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().
+bool
+GDBRemoteRegisterContext::GetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
+                                                GDBRemoteCommunicationClient &gdb_comm)
+{
+    char packet[64];
+    StringExtractorGDBRemote response;
+    int packet_len = 0;
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    if (gdb_comm.GetThreadSuffixSupported())
+        packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4llx;", reg, m_thread.GetID());
+    else
+        packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
+    assert (packet_len < (sizeof(packet) - 1));
+    if (gdb_comm.SendPacketAndWaitForResponse(packet, response, false))
+        return PrivateSetRegisterValue (reg, response);
 
+    return false;
+}
 bool
 GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataExtractor &data)
 {
@@ -187,17 +205,39 @@
                                 SetAllRegisterValid (true);
                     }
                 }
-                else
+                else if (!reg_info->value_regs)
                 {
                     // Get each register individually
+                    GetPrimordialRegister(reg_info, gdb_comm);
+                }
+                else
+                {
+                    // Process this composite register request by delegating to the constituent
+                    // primordial registers.
 
-                    if (thread_suffix_supported)
-                        packet_len = ::snprintf (packet, sizeof(packet), "p%x;thread:%4.4llx;", reg, m_thread.GetID());
-                    else
-                        packet_len = ::snprintf (packet, sizeof(packet), "p%x", reg);
-                    assert (packet_len < (sizeof(packet) - 1));
-                    if (gdb_comm.SendPacketAndWaitForResponse(packet, response, false))
-                        PrivateSetRegisterValue (reg, response);
+                    // Index of the primordial register.
+                    uint32_t prim_reg_idx;
+                    bool success = true;
+                    for (uint32_t idx = 0;
+                         (prim_reg_idx = reg_info->value_regs[idx]) != LLDB_INVALID_REGNUM;
+                         ++idx)
+                    {
+                        // We have a valid primordial regsiter as our constituent.
+                        // Grab the corresponding register info.
+                        const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg_idx);
+                        if (!GetPrimordialRegister(prim_reg_info, gdb_comm))
+                        {
+                            success = false;
+                            // Some failure occurred.  Let's break out of the for loop.
+                            break;
+                        }
+                    }
+                    if (success)
+                    {
+                        // If we reach this point, all primordial register requests have succeeded.
+                        // Validate this composite register.
+                        m_reg_valid[reg_info->kinds[eRegisterKindLLDB]] = true;
+                    }
                 }
             }
         }
@@ -231,7 +271,35 @@
     return false;
 }
 
-
+// Helper function for GDBRemoteRegisterContext::WriteRegisterBytes().
+bool
+GDBRemoteRegisterContext::SetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
+                                                GDBRemoteCommunicationClient &gdb_comm)
+{
+    StreamString packet;
+    StringExtractorGDBRemote response;
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+    packet.Printf ("P%x=", reg);
+    packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
+                              reg_info->byte_size,
+                              lldb::endian::InlHostByteOrder(),
+                              lldb::endian::InlHostByteOrder());
+
+    if (gdb_comm.GetThreadSuffixSupported())
+        packet.Printf (";thread:%4.4llx;", m_thread.GetID());
+
+    // Invalidate just this register
+    m_reg_valid[reg] = false;
+    if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
+                                              packet.GetString().size(),
+                                              response,
+                                              false))
+    {
+        if (response.IsOKResponse())
+            return true;
+    }
+    return false;
+}
 bool
 GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo *reg_info, DataExtractor &data, uint32_t data_offset)
 {
@@ -249,8 +317,6 @@
 //    if (gdb_comm.IsRunning())
 //        return false;
 
-    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
-
     // Grab a pointer to where we are going to put this register
     uint8_t *dst = const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
 
@@ -276,7 +342,7 @@
                 StringExtractorGDBRemote response;
                 if (m_read_all_at_once)
                 {
-                    // Get all registers in one packet
+                    // Set all registers in one packet
                     packet.PutChar ('G');
                     offset = 0;
                     end_offset = m_reg_data.GetByteSize();
@@ -304,30 +370,53 @@
                         }
                     }
                 }
+                else if (!reg_info->value_regs)
+                {
+                    // Set each register individually
+                    return SetPrimordialRegister(reg_info, gdb_comm);
+                }
                 else
                 {
-                    // Get each register individually
-                    packet.Printf ("P%x=", reg);
-                    packet.PutBytesAsRawHex8 (m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
-                                              reg_info->byte_size,
-                                              lldb::endian::InlHostByteOrder(),
-                                              lldb::endian::InlHostByteOrder());
+                    // Process this composite register request by delegating to the constituent
+                    // primordial registers.
 
-                    if (thread_suffix_supported)
-                        packet.Printf (";thread:%4.4llx;", m_thread.GetID());
+                    // Invalidate this composite register first.
+                    m_reg_valid[reg_info->kinds[eRegisterKindLLDB]] = false;
 
-                    // Invalidate just this register
-                    m_reg_valid[reg] = false;
-                    if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
-                                                              packet.GetString().size(),
-                                                              response,
-                                                              false))
+                    // Index of the primordial register.
+                    uint32_t prim_reg_idx;
+                    // For loop index.
+                    uint32_t idx;
+
+                    // Invalidate the invalidate_regs, if present.
+                    if (reg_info->invalidate_regs)
                     {
-                        if (response.IsOKResponse())
+                        for (idx = 0;
+                             (prim_reg_idx = reg_info->invalidate_regs[idx]) != LLDB_INVALID_REGNUM;
+                             ++idx)
                         {
-                            return true;
+                            // Grab the invalidate register info.
+                            const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg_idx);
+                            m_reg_valid[prim_reg_info->kinds[eRegisterKindLLDB]] = false;
                         }
                     }
+
+                    bool success = true;
+                    for (idx = 0;
+                         (prim_reg_idx = reg_info->value_regs[idx]) != LLDB_INVALID_REGNUM;
+                         ++idx)
+                    {
+                        // We have a valid primordial regsiter as our constituent.
+                        // Grab the corresponding register info.
+                        const RegisterInfo *prim_reg_info = GetRegisterInfoAtIndex(prim_reg_idx);
+                        if (!SetPrimordialRegister(prim_reg_info, gdb_comm))
+                        {
+                            success = false;
+                            // Some failure occurred.  Let's break out of the for loop.
+                            break;
+                        }
+                    }
+                    return success;
                 }
             }
         }
@@ -455,6 +544,10 @@
                     {
                         const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
 
+                        // Skip composite registers.
+                        if (reg_info->value_regs)
+                            continue;
+
                         // Only write down the registers that need to be written
                         // if we are going to be doing registers individually.
                         bool write_reg = true;

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h?rev=151939&r1=151938&r2=151939&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h Fri Mar  2 15:32:50 2012
@@ -21,7 +21,7 @@
 #include "lldb/Core/ConstString.h"
 #include "lldb/Core/DataExtractor.h"
 #include "lldb/Target/RegisterContext.h"
-
+#include "GDBRemoteCommunicationClient.h"
 
 class ThreadGDBRemote;
 class ProcessGDBRemote;
@@ -246,6 +246,13 @@
     bool m_read_all_at_once;
 
 private:
+    // Helper function for ReadRegisterBytes().
+    bool GetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
+                               GDBRemoteCommunicationClient &gdb_comm);
+    // Helper function for WriteRegisterBytes().
+    bool SetPrimordialRegister(const lldb_private::RegisterInfo *reg_info,
+                               GDBRemoteCommunicationClient &gdb_comm);
+
     //------------------------------------------------------------------
     // For GDBRemoteRegisterContext only
     //------------------------------------------------------------------





More information about the lldb-commits mailing list