[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