Remove the last manually constructed packet from gdb-remote register context + small refactor
Summary:
The tricky part here was that the exisiting implementation of WriteAllRegisters was expecting
hex-encoded data (as that was what the first implementation I replaced was using, but here we had
binary data to begin with. I thought the read/write register functions would be more useful if
they handled the hex-encoding themselves (all the other client functions provide the responses in
a more-or-less digested form). The read functions return a DataBuffer, so they can allocate as
much memory as they need to, while the write functions functions take an llvm::ArrayRef, as that
can be constructed from pretty much anything.
Reviewers: clayborg
Subscribers: lldb-commits
Differential Revision: https://reviews.llvm.org/D23659
llvm-svn: 279232
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
index d893b86..79ff5d1 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -24,6 +24,7 @@
#include "lldb/Core/State.h"
#include "lldb/Core/StreamGDBRemote.h"
#include "lldb/Core/StreamString.h"
+#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Host/HostInfo.h"
#include "lldb/Host/StringConvert.h"
#include "lldb/Host/TimeValue.h"
@@ -3494,45 +3495,58 @@
return m_avoid_g_packets == eLazyBoolYes;
}
-bool
-GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, uint32_t reg, StringExtractorGDBRemote &response)
+DataBufferSP
+GDBRemoteCommunicationClient::ReadRegister(lldb::tid_t tid, uint32_t reg)
{
StreamString payload;
payload.Printf("p%x", reg);
- return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) ==
- PacketResult::Success;
+ StringExtractorGDBRemote response;
+ if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) != PacketResult::Success ||
+ !response.IsNormalResponse())
+ return nullptr;
+
+ DataBufferSP buffer_sp(new DataBufferHeap(response.GetStringRef().size() / 2, 0));
+ response.GetHexBytes(buffer_sp->GetBytes(), buffer_sp->GetByteSize(), '\xcc');
+ return buffer_sp;
}
-
-bool
-GDBRemoteCommunicationClient::ReadAllRegisters (lldb::tid_t tid, StringExtractorGDBRemote &response)
+DataBufferSP
+GDBRemoteCommunicationClient::ReadAllRegisters(lldb::tid_t tid)
{
StreamString payload;
payload.PutChar('g');
- return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) ==
- PacketResult::Success;
+ StringExtractorGDBRemote response;
+ if (SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) != PacketResult::Success ||
+ !response.IsNormalResponse())
+ return nullptr;
+
+ DataBufferSP buffer_sp(new DataBufferHeap(response.GetStringRef().size() / 2, 0));
+ response.GetHexBytes(buffer_sp->GetBytes(), buffer_sp->GetByteSize(), '\xcc');
+ return buffer_sp;
}
bool
-GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid, uint32_t reg_num, llvm::StringRef data)
+GDBRemoteCommunicationClient::WriteRegister(lldb::tid_t tid, uint32_t reg_num, llvm::ArrayRef<uint8_t> data)
{
StreamString payload;
payload.Printf("P%x=", reg_num);
payload.PutBytesAsRawHex8(data.data(), data.size(), endian::InlHostByteOrder(), endian::InlHostByteOrder());
StringExtractorGDBRemote response;
return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) ==
- PacketResult::Success;
+ PacketResult::Success &&
+ response.IsOKResponse();
}
bool
-GDBRemoteCommunicationClient::WriteAllRegisters(lldb::tid_t tid, llvm::StringRef data)
+GDBRemoteCommunicationClient::WriteAllRegisters(lldb::tid_t tid, llvm::ArrayRef<uint8_t> data)
{
StreamString payload;
payload.PutChar('G');
- payload.Write(data.data(), data.size());
+ payload.PutBytesAsRawHex8(data.data(), data.size(), endian::InlHostByteOrder(), endian::InlHostByteOrder());
StringExtractorGDBRemote response;
return SendThreadSpecificPacketAndWaitForResponse(tid, std::move(payload), response, false) ==
- PacketResult::Success;
+ PacketResult::Success &&
+ response.IsOKResponse();
}
bool
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
index 54e7079..eeeecb5 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -10,6 +10,8 @@
#ifndef liblldb_GDBRemoteCommunicationClient_h_
#define liblldb_GDBRemoteCommunicationClient_h_
+#include "GDBRemoteClientBase.h"
+
// C Includes
// C++ Includes
#include <chrono>
@@ -24,8 +26,6 @@
#include "lldb/Core/StructuredData.h"
#include "lldb/Target/Process.h"
-#include "GDBRemoteClientBase.h"
-
namespace lldb_private {
namespace process_gdb_remote {
@@ -485,23 +485,20 @@
bool
CalculateMD5 (const FileSpec& file_spec, uint64_t &high, uint64_t &low);
-
- bool
+ lldb::DataBufferSP
ReadRegister(lldb::tid_t tid,
- uint32_t reg_num, // Must be the eRegisterKindProcessPlugin register number, to be sent to the remote
- StringExtractorGDBRemote &response);
+ uint32_t reg_num); // Must be the eRegisterKindProcessPlugin register number
- bool
- ReadAllRegisters (lldb::tid_t tid,
- StringExtractorGDBRemote &response);
+ lldb::DataBufferSP
+ ReadAllRegisters(lldb::tid_t tid);
bool
WriteRegister(lldb::tid_t tid, uint32_t reg_num, // eRegisterKindProcessPlugin register number
- llvm::StringRef data);
+ llvm::ArrayRef<uint8_t> data);
bool
- WriteAllRegisters(lldb::tid_t tid, llvm::StringRef data);
+ WriteAllRegisters(lldb::tid_t tid, llvm::ArrayRef<uint8_t> data);
bool
SaveRegisterState(lldb::tid_t tid, uint32_t &save_id);
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
index dd8ac9e..76a7d7d 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp
@@ -130,7 +130,7 @@
}
bool
-GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
+GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data)
{
const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg);
if (reg_info == NULL)
@@ -139,14 +139,15 @@
// Invalidate if needed
InvalidateIfNeeded(false);
- const uint32_t reg_byte_size = reg_info->byte_size;
- const size_t bytes_copied = response.GetHexBytes (const_cast<uint8_t*>(m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)), reg_byte_size, '\xcc');
- bool success = bytes_copied == reg_byte_size;
+ const size_t reg_byte_size = reg_info->byte_size;
+ memcpy(const_cast<uint8_t *>(m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)), data.data(),
+ std::min(data.size(), reg_byte_size));
+ bool success = data.size() >= reg_byte_size;
if (success)
{
SetRegisterIsValid(reg, true);
}
- else if (bytes_copied > 0)
+ else if (data.size() > 0)
{
// Only set register is valid to false if we copied some bytes, else
// leave it as it was.
@@ -209,8 +210,9 @@
const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB];
const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin];
StringExtractorGDBRemote response;
- if (gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg, response))
- return PrivateSetRegisterValue (lldb_reg, response);
+ if (DataBufferSP buffer_sp = gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg))
+ return PrivateSetRegisterValue(lldb_reg,
+ llvm::ArrayRef<uint8_t>(buffer_sp->GetBytes(), buffer_sp->GetByteSize()));
return false;
}
@@ -234,15 +236,19 @@
{
if (m_read_all_at_once)
{
- StringExtractorGDBRemote response;
- if (!gdb_comm.ReadAllRegisters(m_thread.GetProtocolID(), response))
- return false;
- if (response.IsNormalResponse())
- if (response.GetHexBytes(const_cast<void *>(reinterpret_cast<const void *>(m_reg_data.GetDataStart())),
- m_reg_data.GetByteSize(), '\xcc') == m_reg_data.GetByteSize())
- SetAllRegisterValid (true);
+ if (DataBufferSP buffer_sp = gdb_comm.ReadAllRegisters(m_thread.GetProtocolID()))
+ {
+ memcpy(const_cast<uint8_t *>(m_reg_data.GetDataStart()), buffer_sp->GetBytes(),
+ std::min(buffer_sp->GetByteSize(), m_reg_data.GetByteSize()));
+ if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize())
+ {
+ SetAllRegisterValid(true);
+ return true;
+ }
+ }
+ return false;
}
- else if (reg_info->value_regs)
+ if (reg_info->value_regs)
{
// Process this composite register request by delegating to the constituent
// primordial registers.
@@ -330,8 +336,7 @@
return gdb_comm.WriteRegister(
m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin],
- llvm::StringRef(reinterpret_cast<const char *>(m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size)),
- reg_info->byte_size));
+ {m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size), reg_info->byte_size});
}
bool
@@ -371,38 +376,18 @@
GDBRemoteClientBase::Lock lock(gdb_comm, false);
if (lock)
{
- const bool thread_suffix_supported = gdb_comm.GetThreadSuffixSupported();
- ProcessSP process_sp (m_thread.GetProcess());
- if (thread_suffix_supported || static_cast<ProcessGDBRemote *>(process_sp.get())->GetGDBRemote().SetCurrentThread(m_thread.GetProtocolID()))
- {
- StreamString packet;
- StringExtractorGDBRemote response;
-
if (m_read_all_at_once)
{
- // Set all registers in one packet
- packet.PutChar ('G');
- packet.PutBytesAsRawHex8 (m_reg_data.GetDataStart(),
- m_reg_data.GetByteSize(),
- endian::InlHostByteOrder(),
- endian::InlHostByteOrder());
-
- if (thread_suffix_supported)
- packet.Printf (";thread:%4.4" PRIx64 ";", m_thread.GetProtocolID());
-
// Invalidate all register values
InvalidateIfNeeded (true);
- if (gdb_comm.SendPacketAndWaitForResponse(packet.GetString().c_str(),
- packet.GetString().size(),
- response,
- false) == GDBRemoteCommunication::PacketResult::Success)
+ // Set all registers in one packet
+ if (gdb_comm.WriteAllRegisters(m_thread.GetProtocolID(),
+ {m_reg_data.GetDataStart(), m_reg_data.GetByteSize()}))
+
{
SetAllRegisterValid (false);
- if (response.IsOKResponse())
- {
- return true;
- }
+ return true;
}
}
else
@@ -451,7 +436,6 @@
return success;
}
- }
}
else
{
@@ -533,8 +517,6 @@
GDBRemoteCommunicationClient &gdb_comm (((ProcessGDBRemote *)process)->GetGDBRemote());
- StringExtractorGDBRemote response;
-
const bool use_g_packet = gdb_comm.AvoidGPackets ((ProcessGDBRemote *)process) == false;
GDBRemoteClientBase::Lock lock(gdb_comm, false);
@@ -543,40 +525,22 @@
if (gdb_comm.SyncThreadState(m_thread.GetProtocolID()))
InvalidateAllRegisters();
- if (use_g_packet && gdb_comm.ReadAllRegisters(m_thread.GetProtocolID(), response))
- {
- if (response.IsErrorResponse())
- return false;
-
- std::string &response_str = response.GetStringRef();
- if (!isxdigit(response_str[0]))
- return false;
-
- data_sp.reset(new DataBufferHeap(response_str.c_str(), response_str.size()));
+ if (use_g_packet && (data_sp = gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())))
return true;
- }
- else
+
+ // We're going to read each register
+ // individually and store them as binary data in a buffer.
+ const RegisterInfo *reg_info;
+
+ for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; i++)
{
- // For the use_g_packet == false case, we're going to read each register
- // individually and store them as binary data in a buffer instead of as ascii
- // characters.
- const RegisterInfo *reg_info;
-
- // data_sp will take ownership of this DataBufferHeap pointer soon.
- DataBufferSP reg_ctx(new DataBufferHeap(m_reg_info.GetRegisterDataByteSize(), 0));
-
- for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != NULL; i++)
- {
- if (reg_info->value_regs) // skip registers that are slices of real registers
- continue;
- ReadRegisterBytes(reg_info, m_reg_data);
- // ReadRegisterBytes saves the contents of the register in to the m_reg_data buffer
- }
- memcpy(reg_ctx->GetBytes(), m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize());
-
- data_sp = reg_ctx;
- return true;
+ if (reg_info->value_regs) // skip registers that are slices of real registers
+ continue;
+ ReadRegisterBytes(reg_info, m_reg_data);
+ // ReadRegisterBytes saves the contents of the register in to the m_reg_data buffer
}
+ data_sp.reset(new DataBufferHeap(m_reg_data.GetDataStart(), m_reg_info.GetRegisterDataByteSize()));
+ return true;
}
else
{
@@ -616,31 +580,19 @@
const bool use_g_packet = gdb_comm.AvoidGPackets ((ProcessGDBRemote *)process) == false;
- StringExtractorGDBRemote response;
GDBRemoteClientBase::Lock lock(gdb_comm, false);
if (lock)
{
// The data_sp contains the G response packet.
- llvm::StringRef data(reinterpret_cast<const char *>(data_sp->GetBytes()), data_sp->GetByteSize());
if (use_g_packet)
{
- if (gdb_comm.WriteAllRegisters(m_thread.GetProtocolID(), data))
+ if (gdb_comm.WriteAllRegisters(m_thread.GetProtocolID(), {data_sp->GetBytes(), data_sp->GetByteSize()}))
return true;
uint32_t num_restored = 0;
// We need to manually go through all of the registers and
// restore them manually
-
- response.GetStringRef() = data;
- DataBufferHeap buffer(data.size() / 2, 0);
-
- const uint32_t bytes_extracted = response.GetHexBytes(buffer.GetBytes(), buffer.GetByteSize(), '\xcc');
-
- DataExtractor restore_data(buffer.GetBytes(), buffer.GetByteSize(), m_reg_data.GetByteOrder(),
- m_reg_data.GetAddressByteSize());
-
- if (bytes_extracted < restore_data.GetByteSize())
- restore_data.SetData(restore_data.GetDataStart(), bytes_extracted, m_reg_data.GetByteOrder());
+ DataExtractor restore_data(data_sp, m_reg_data.GetByteOrder(), m_reg_data.GetAddressByteSize());
const RegisterInfo *reg_info;
@@ -716,12 +668,12 @@
const uint32_t reg_byte_size = reg_info->byte_size;
- const char *restore_src = (const char *)restore_data.PeekData(register_offset, reg_byte_size);
+ const uint8_t *restore_src = restore_data.PeekData(register_offset, reg_byte_size);
if (restore_src)
{
SetRegisterIsValid(reg, false);
if (gdb_comm.WriteRegister(m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin],
- llvm::StringRef(restore_src, reg_byte_size)))
+ {restore_src, reg_byte_size}))
++num_restored;
}
}
@@ -759,13 +711,9 @@
}
SetRegisterIsValid(reg_info, false);
- if (gdb_comm.WriteRegister(
- m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin],
- llvm::StringRef(reinterpret_cast<const char *>(data_sp->GetBytes() + reg_info->byte_offset),
- reg_info->byte_size)))
- {
+ if (gdb_comm.WriteRegister(m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin],
+ {data_sp->GetBytes() + reg_info->byte_offset, reg_info->byte_size}))
++num_restored;
- }
}
return num_restored > 0;
}
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
index 0021b5e..c1d8249 100644
--- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
+++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.h
@@ -107,8 +107,8 @@
uint32_t data_offset);
bool
- PrivateSetRegisterValue (uint32_t reg, StringExtractor &response);
-
+ PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data);
+
bool
PrivateSetRegisterValue (uint32_t reg, uint64_t val);
diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
index be5c3b5..67fa0ee 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1991,7 +1991,10 @@
{
StringExtractor reg_value_extractor;
reg_value_extractor.GetStringRef() = pair.second;
- gdb_thread->PrivateSetRegisterValue (pair.first, reg_value_extractor);
+ DataBufferSP buffer_sp(new DataBufferHeap(reg_value_extractor.GetStringRef().size() / 2, 0));
+ reg_value_extractor.GetHexBytes(buffer_sp->GetBytes(), buffer_sp->GetByteSize(), '\xcc');
+ gdb_thread->PrivateSetRegisterValue(
+ pair.first, llvm::ArrayRef<uint8_t>(buffer_sp->GetBytes(), buffer_sp->GetByteSize()));
}
thread_sp->SetName (thread_name.empty() ? NULL : thread_name.c_str());
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
index a4af12c..02a617b 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp
@@ -380,11 +380,11 @@
}
bool
-ThreadGDBRemote::PrivateSetRegisterValue (uint32_t reg, StringExtractor &response)
+ThreadGDBRemote::PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data)
{
GDBRemoteRegisterContext *gdb_reg_ctx = static_cast<GDBRemoteRegisterContext *>(GetRegisterContext ().get());
assert (gdb_reg_ctx);
- return gdb_reg_ctx->PrivateSetRegisterValue (reg, response);
+ return gdb_reg_ctx->PrivateSetRegisterValue(reg, data);
}
bool
diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
index d7619f4..d452042 100644
--- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
+++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h
@@ -130,8 +130,7 @@
lldb_private::LazyBool m_associated_with_libdispatch_queue;
bool
- PrivateSetRegisterValue (uint32_t reg,
- StringExtractor &response);
+ PrivateSetRegisterValue(uint32_t reg, llvm::ArrayRef<uint8_t> data);
bool
PrivateSetRegisterValue (uint32_t reg,