diff options
author | Johnny Chen <johnny.chen@apple.com> | 2012-03-02 21:32:50 +0000 |
---|---|---|
committer | Johnny Chen <johnny.chen@apple.com> | 2012-03-02 21:32:50 +0000 |
commit | 213ba7c7c36e6e970f5bd243e888c13f6880c739 (patch) | |
tree | 30c949d01a99bd80972e897ff8beedffd8190499 /lldb/source/Plugins/Process | |
parent | aa1f96add58c968e6693f63bb8ab0df06d175e07 (diff) | |
download | bcm5719-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.cpp | 151 | ||||
-rw-r--r-- | lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h | 9 |
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 //------------------------------------------------------------------ |