mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2025-02-05 00:49:43 +00:00
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
This commit is contained in:
parent
b8824a5d3f
commit
b42b48e051
@ -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 @@ GDBRemoteCommunicationClient::AvoidGPackets (ProcessGDBRemote *process)
|
||||
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
|
||||
|
@ -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 @@ public:
|
||||
|
||||
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);
|
||||
|
@ -130,7 +130,7 @@ GDBRemoteRegisterContext::ReadRegister (const RegisterInfo *reg_info, RegisterVa
|
||||
}
|
||||
|
||||
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 @@ GDBRemoteRegisterContext::PrivateSetRegisterValue (uint32_t reg, StringExtractor
|
||||
// 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 @@ GDBRemoteRegisterContext::GetPrimordialRegister(const RegisterInfo *reg_info,
|
||||
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 @@ GDBRemoteRegisterContext::ReadRegisterBytes (const RegisterInfo *reg_info, DataE
|
||||
{
|
||||
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 @@ GDBRemoteRegisterContext::SetPrimordialRegister(const RegisterInfo *reg_info,
|
||||
|
||||
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 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const RegisterInfo *reg_info, Data
|
||||
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 @@ GDBRemoteRegisterContext::WriteRegisterBytes (const RegisterInfo *reg_info, Data
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -533,8 +517,6 @@ GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
|
||||
|
||||
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 @@ GDBRemoteRegisterContext::ReadAllRegisterValues (lldb::DataBufferSP &data_sp)
|
||||
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 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
|
||||
|
||||
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 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
|
||||
|
||||
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 @@ GDBRemoteRegisterContext::WriteAllRegisterValues (const lldb::DataBufferSP &data
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -107,8 +107,8 @@ protected:
|
||||
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);
|
||||
|
||||
|
@ -1991,7 +1991,10 @@ ProcessGDBRemote::SetThreadStopInfo (lldb::tid_t tid,
|
||||
{
|
||||
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());
|
||||
|
@ -380,11 +380,11 @@ ThreadGDBRemote::CreateRegisterContextForFrame (StackFrame *frame)
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -130,8 +130,7 @@ protected:
|
||||
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,
|
||||
|
@ -18,6 +18,9 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h"
|
||||
#include "lldb/Core/DataBuffer.h"
|
||||
|
||||
#include "llvm/ADT/ArrayRef.h"
|
||||
|
||||
using namespace lldb_private::process_gdb_remote;
|
||||
using namespace lldb_private;
|
||||
@ -54,7 +57,10 @@ HandlePacket(MockServer &server, llvm::StringRef expected, llvm::StringRef respo
|
||||
ASSERT_EQ(PacketResult::Success, server.SendPacket(response));
|
||||
}
|
||||
|
||||
const char all_registers[] = "404142434445464748494a4b4c4d4e4f";
|
||||
uint8_t all_registers[] = {'@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O'};
|
||||
std::string all_registers_hex = "404142434445464748494a4b4c4d4e4f";
|
||||
uint8_t one_register[] = {'A', 'B', 'C', 'D'};
|
||||
std::string one_register_hex = "41424344";
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
@ -73,16 +79,16 @@ TEST_F(GDBRemoteCommunicationClientTest, WriteRegister)
|
||||
const lldb::tid_t tid = 0x47;
|
||||
const uint32_t reg_num = 4;
|
||||
std::future<bool> write_result =
|
||||
std::async(std::launch::async, [&] { return client.WriteRegister(tid, reg_num, "ABCD"); });
|
||||
std::async(std::launch::async, [&] { return client.WriteRegister(tid, reg_num, one_register); });
|
||||
|
||||
Handle_QThreadSuffixSupported(server, true);
|
||||
|
||||
HandlePacket(server, "P4=41424344;thread:0047;", "OK");
|
||||
HandlePacket(server, "P4=" + one_register_hex + ";thread:0047;", "OK");
|
||||
ASSERT_TRUE(write_result.get());
|
||||
|
||||
write_result = std::async(std::launch::async, [&] { return client.WriteAllRegisters(tid, all_registers); });
|
||||
|
||||
HandlePacket(server, std::string("G") + all_registers + ";thread:0047;", "OK");
|
||||
HandlePacket(server, "G" + all_registers_hex + ";thread:0047;", "OK");
|
||||
ASSERT_TRUE(write_result.get());
|
||||
}
|
||||
|
||||
@ -97,16 +103,16 @@ TEST_F(GDBRemoteCommunicationClientTest, WriteRegisterNoSuffix)
|
||||
const lldb::tid_t tid = 0x47;
|
||||
const uint32_t reg_num = 4;
|
||||
std::future<bool> write_result =
|
||||
std::async(std::launch::async, [&] { return client.WriteRegister(tid, reg_num, "ABCD"); });
|
||||
std::async(std::launch::async, [&] { return client.WriteRegister(tid, reg_num, one_register); });
|
||||
|
||||
Handle_QThreadSuffixSupported(server, false);
|
||||
HandlePacket(server, "Hg47", "OK");
|
||||
HandlePacket(server, "P4=41424344", "OK");
|
||||
HandlePacket(server, "P4=" + one_register_hex, "OK");
|
||||
ASSERT_TRUE(write_result.get());
|
||||
|
||||
write_result = std::async(std::launch::async, [&] { return client.WriteAllRegisters(tid, all_registers); });
|
||||
|
||||
HandlePacket(server, std::string("G") + all_registers, "OK");
|
||||
HandlePacket(server, "G" + all_registers_hex, "OK");
|
||||
ASSERT_TRUE(write_result.get());
|
||||
}
|
||||
|
||||
@ -122,19 +128,21 @@ TEST_F(GDBRemoteCommunicationClientTest, ReadRegister)
|
||||
const uint32_t reg_num = 4;
|
||||
std::future<bool> async_result = std::async(std::launch::async, [&] { return client.GetpPacketSupported(tid); });
|
||||
Handle_QThreadSuffixSupported(server, true);
|
||||
HandlePacket(server, "p0;thread:0047;", "41424344");
|
||||
HandlePacket(server, "p0;thread:0047;", one_register_hex);
|
||||
ASSERT_TRUE(async_result.get());
|
||||
|
||||
StringExtractorGDBRemote response;
|
||||
async_result = std::async(std::launch::async, [&] { return client.ReadRegister(tid, reg_num, response); });
|
||||
std::future<DataBufferSP> read_result =
|
||||
std::async(std::launch::async, [&] { return client.ReadRegister(tid, reg_num); });
|
||||
HandlePacket(server, "p4;thread:0047;", "41424344");
|
||||
ASSERT_TRUE(async_result.get());
|
||||
ASSERT_EQ("41424344", response.GetStringRef());
|
||||
auto buffer_sp = read_result.get();
|
||||
ASSERT_TRUE(bool(buffer_sp));
|
||||
ASSERT_EQ(0, memcmp(buffer_sp->GetBytes(), one_register, sizeof one_register));
|
||||
|
||||
async_result = std::async(std::launch::async, [&] { return client.ReadAllRegisters(tid, response); });
|
||||
HandlePacket(server, "g;thread:0047;", all_registers);
|
||||
ASSERT_TRUE(async_result.get());
|
||||
ASSERT_EQ(all_registers, response.GetStringRef());
|
||||
read_result = std::async(std::launch::async, [&] { return client.ReadAllRegisters(tid); });
|
||||
HandlePacket(server, "g;thread:0047;", all_registers_hex);
|
||||
buffer_sp = read_result.get();
|
||||
ASSERT_TRUE(bool(buffer_sp));
|
||||
ASSERT_EQ(0, memcmp(buffer_sp->GetBytes(), all_registers, sizeof all_registers));
|
||||
}
|
||||
|
||||
TEST_F(GDBRemoteCommunicationClientTest, SaveRestoreRegistersNoSuffix)
|
||||
|
Loading…
x
Reference in New Issue
Block a user