summaryrefslogtreecommitdiffstats
path: root/lldb/source/Plugins/Process
diff options
context:
space:
mode:
authorJohnny Chen <johnny.chen@apple.com>2012-03-02 21:32:50 +0000
committerJohnny Chen <johnny.chen@apple.com>2012-03-02 21:32:50 +0000
commit213ba7c7c36e6e970f5bd243e888c13f6880c739 (patch)
tree30c949d01a99bd80972e897ff8beedffd8190499 /lldb/source/Plugins/Process
parentaa1f96add58c968e6693f63bb8ab0df06d175e07 (diff)
downloadbcm5719-llvm-213ba7c7c36e6e970f5bd243e888c13f6880c739.tar.gz
bcm5719-llvm-213ba7c7c36e6e970f5bd243e888c13f6880c739.zip
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} llvm-svn: 151939
Diffstat (limited to 'lldb/source/Plugins/Process')
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp151
-rw-r--r--lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h9
2 files changed, 130 insertions, 30 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index 8d930ec26d7..77051fffc6e 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -143,7 +143,25 @@ GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor
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 @@ GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataE
SetAllRegisterValid (true);
}
}
- else
+ else if (!reg_info->value_regs)
{
// Get each register individually
-
- 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);
+ GetPrimordialRegister(reg_info, gdb_comm);
+ }
+ else
+ {
+ // Process this composite register request by delegating to the constituent
+ // primordial registers.
+
+ // 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 @@ GDBRemoteRegisterContext::WriteRegister (const RegisterInfo *reg_info,
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 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo *
// 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 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo *
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 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const lldb_private::RegisterInfo *
}
}
}
+ 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 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
{
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;
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 9f96e77cb54..257baf4df83 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -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 @@ protected:
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
//------------------------------------------------------------------
OpenPOWER on IntegriCloud