xref: /freebsd-src/contrib/llvm-project/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp (revision 5f757f3ff9144b609b3c433dfd370cc6bdc191ad)
15ffd83dbSDimitry Andric //===-- GDBRemoteRegisterContext.cpp --------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "GDBRemoteRegisterContext.h"
100b57cec5SDimitry Andric 
11*5f757f3fSDimitry Andric #include "ProcessGDBRemote.h"
12*5f757f3fSDimitry Andric #include "ProcessGDBRemoteLog.h"
13*5f757f3fSDimitry Andric #include "ThreadGDBRemote.h"
14*5f757f3fSDimitry Andric #include "Utility/ARM_DWARF_Registers.h"
15*5f757f3fSDimitry Andric #include "Utility/ARM_ehframe_Registers.h"
16*5f757f3fSDimitry Andric #include "lldb/Core/Architecture.h"
170b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
180b57cec5SDimitry Andric #include "lldb/Target/Target.h"
190b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
200b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
210b57cec5SDimitry Andric #include "lldb/Utility/RegisterValue.h"
220b57cec5SDimitry Andric #include "lldb/Utility/Scalar.h"
230b57cec5SDimitry Andric #include "lldb/Utility/StreamString.h"
240b57cec5SDimitry Andric #include "lldb/Utility/StringExtractorGDBRemote.h"
250b57cec5SDimitry Andric 
260b57cec5SDimitry Andric #include <memory>
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric using namespace lldb;
290b57cec5SDimitry Andric using namespace lldb_private;
300b57cec5SDimitry Andric using namespace lldb_private::process_gdb_remote;
310b57cec5SDimitry Andric 
320b57cec5SDimitry Andric // GDBRemoteRegisterContext constructor
GDBRemoteRegisterContext(ThreadGDBRemote & thread,uint32_t concrete_frame_idx,GDBRemoteDynamicRegisterInfoSP reg_info_sp,bool read_all_at_once,bool write_all_at_once)330b57cec5SDimitry Andric GDBRemoteRegisterContext::GDBRemoteRegisterContext(
340b57cec5SDimitry Andric     ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
35e8d8bef9SDimitry Andric     GDBRemoteDynamicRegisterInfoSP reg_info_sp, bool read_all_at_once,
36480093f4SDimitry Andric     bool write_all_at_once)
37e8d8bef9SDimitry Andric     : RegisterContext(thread, concrete_frame_idx),
38e8d8bef9SDimitry Andric       m_reg_info_sp(std::move(reg_info_sp)), m_reg_valid(), m_reg_data(),
39e8d8bef9SDimitry Andric       m_read_all_at_once(read_all_at_once),
40fe6060f1SDimitry Andric       m_write_all_at_once(write_all_at_once), m_gpacket_cached(false) {
410b57cec5SDimitry Andric   // Resize our vector of bools to contain one bool for every register. We will
420b57cec5SDimitry Andric   // use these boolean values to know when a register value is valid in
430b57cec5SDimitry Andric   // m_reg_data.
44e8d8bef9SDimitry Andric   m_reg_valid.resize(m_reg_info_sp->GetNumRegisters());
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric   // Make a heap based buffer that is big enough to store all registers
470b57cec5SDimitry Andric   DataBufferSP reg_data_sp(
48e8d8bef9SDimitry Andric       new DataBufferHeap(m_reg_info_sp->GetRegisterDataByteSize(), 0));
490b57cec5SDimitry Andric   m_reg_data.SetData(reg_data_sp);
500b57cec5SDimitry Andric   m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder());
510b57cec5SDimitry Andric }
520b57cec5SDimitry Andric 
530b57cec5SDimitry Andric // Destructor
54fe6060f1SDimitry Andric GDBRemoteRegisterContext::~GDBRemoteRegisterContext() = default;
550b57cec5SDimitry Andric 
InvalidateAllRegisters()560b57cec5SDimitry Andric void GDBRemoteRegisterContext::InvalidateAllRegisters() {
570b57cec5SDimitry Andric   SetAllRegisterValid(false);
580b57cec5SDimitry Andric }
590b57cec5SDimitry Andric 
SetAllRegisterValid(bool b)600b57cec5SDimitry Andric void GDBRemoteRegisterContext::SetAllRegisterValid(bool b) {
61fe6060f1SDimitry Andric   m_gpacket_cached = b;
620b57cec5SDimitry Andric   std::vector<bool>::iterator pos, end = m_reg_valid.end();
630b57cec5SDimitry Andric   for (pos = m_reg_valid.begin(); pos != end; ++pos)
640b57cec5SDimitry Andric     *pos = b;
650b57cec5SDimitry Andric }
660b57cec5SDimitry Andric 
GetRegisterCount()670b57cec5SDimitry Andric size_t GDBRemoteRegisterContext::GetRegisterCount() {
68e8d8bef9SDimitry Andric   return m_reg_info_sp->GetNumRegisters();
690b57cec5SDimitry Andric }
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)720b57cec5SDimitry Andric GDBRemoteRegisterContext::GetRegisterInfoAtIndex(size_t reg) {
73349cc55cSDimitry Andric   return m_reg_info_sp->GetRegisterInfoAtIndex(reg);
740b57cec5SDimitry Andric }
750b57cec5SDimitry Andric 
GetRegisterSetCount()760b57cec5SDimitry Andric size_t GDBRemoteRegisterContext::GetRegisterSetCount() {
77e8d8bef9SDimitry Andric   return m_reg_info_sp->GetNumRegisterSets();
780b57cec5SDimitry Andric }
790b57cec5SDimitry Andric 
GetRegisterSet(size_t reg_set)800b57cec5SDimitry Andric const RegisterSet *GDBRemoteRegisterContext::GetRegisterSet(size_t reg_set) {
81e8d8bef9SDimitry Andric   return m_reg_info_sp->GetRegisterSet(reg_set);
820b57cec5SDimitry Andric }
830b57cec5SDimitry Andric 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & value)840b57cec5SDimitry Andric bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info,
850b57cec5SDimitry Andric                                             RegisterValue &value) {
860b57cec5SDimitry Andric   // Read the register
87349cc55cSDimitry Andric   if (ReadRegisterBytes(reg_info)) {
88480093f4SDimitry Andric     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
89480093f4SDimitry Andric     if (m_reg_valid[reg] == false)
90480093f4SDimitry Andric       return false;
91349cc55cSDimitry Andric     if (reg_info->value_regs &&
92349cc55cSDimitry Andric         reg_info->value_regs[0] != LLDB_INVALID_REGNUM &&
93349cc55cSDimitry Andric         reg_info->value_regs[1] != LLDB_INVALID_REGNUM) {
94349cc55cSDimitry Andric       std::vector<char> combined_data;
95349cc55cSDimitry Andric       uint32_t offset = 0;
96349cc55cSDimitry Andric       for (int i = 0; reg_info->value_regs[i] != LLDB_INVALID_REGNUM; i++) {
97349cc55cSDimitry Andric         const RegisterInfo *parent_reg = GetRegisterInfo(
98349cc55cSDimitry Andric             eRegisterKindLLDB, reg_info->value_regs[i]);
99349cc55cSDimitry Andric         if (!parent_reg)
100349cc55cSDimitry Andric           return false;
101349cc55cSDimitry Andric         combined_data.resize(offset + parent_reg->byte_size);
102349cc55cSDimitry Andric         if (m_reg_data.CopyData(parent_reg->byte_offset, parent_reg->byte_size,
103349cc55cSDimitry Andric                                 combined_data.data() + offset) !=
104349cc55cSDimitry Andric             parent_reg->byte_size)
105349cc55cSDimitry Andric           return false;
106349cc55cSDimitry Andric         offset += parent_reg->byte_size;
107349cc55cSDimitry Andric       }
108349cc55cSDimitry Andric 
109349cc55cSDimitry Andric       Status error;
110349cc55cSDimitry Andric       return value.SetFromMemoryData(
111bdd1243dSDimitry Andric                  *reg_info, combined_data.data(), combined_data.size(),
112349cc55cSDimitry Andric                  m_reg_data.GetByteOrder(), error) == combined_data.size();
113349cc55cSDimitry Andric     } else {
1140b57cec5SDimitry Andric       const bool partial_data_ok = false;
1150b57cec5SDimitry Andric       Status error(value.SetValueFromData(
116bdd1243dSDimitry Andric           *reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok));
1170b57cec5SDimitry Andric       return error.Success();
1180b57cec5SDimitry Andric     }
119349cc55cSDimitry Andric   }
1200b57cec5SDimitry Andric   return false;
1210b57cec5SDimitry Andric }
1220b57cec5SDimitry Andric 
PrivateSetRegisterValue(uint32_t reg,llvm::ArrayRef<uint8_t> data)1230b57cec5SDimitry Andric bool GDBRemoteRegisterContext::PrivateSetRegisterValue(
1240b57cec5SDimitry Andric     uint32_t reg, llvm::ArrayRef<uint8_t> data) {
1250b57cec5SDimitry Andric   const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
1260b57cec5SDimitry Andric   if (reg_info == nullptr)
1270b57cec5SDimitry Andric     return false;
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric   // Invalidate if needed
1300b57cec5SDimitry Andric   InvalidateIfNeeded(false);
1310b57cec5SDimitry Andric 
1320b57cec5SDimitry Andric   const size_t reg_byte_size = reg_info->byte_size;
1330b57cec5SDimitry Andric   memcpy(const_cast<uint8_t *>(
1340b57cec5SDimitry Andric              m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)),
1350b57cec5SDimitry Andric          data.data(), std::min(data.size(), reg_byte_size));
1360b57cec5SDimitry Andric   bool success = data.size() >= reg_byte_size;
1370b57cec5SDimitry Andric   if (success) {
1380b57cec5SDimitry Andric     SetRegisterIsValid(reg, true);
1390b57cec5SDimitry Andric   } else if (data.size() > 0) {
1400b57cec5SDimitry Andric     // Only set register is valid to false if we copied some bytes, else leave
1410b57cec5SDimitry Andric     // it as it was.
1420b57cec5SDimitry Andric     SetRegisterIsValid(reg, false);
1430b57cec5SDimitry Andric   }
1440b57cec5SDimitry Andric   return success;
1450b57cec5SDimitry Andric }
1460b57cec5SDimitry Andric 
PrivateSetRegisterValue(uint32_t reg,uint64_t new_reg_val)1470b57cec5SDimitry Andric bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg,
1480b57cec5SDimitry Andric                                                        uint64_t new_reg_val) {
1490b57cec5SDimitry Andric   const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
1500b57cec5SDimitry Andric   if (reg_info == nullptr)
1510b57cec5SDimitry Andric     return false;
1520b57cec5SDimitry Andric 
1530b57cec5SDimitry Andric   // Early in process startup, we can get a thread that has an invalid byte
1540b57cec5SDimitry Andric   // order because the process hasn't been completely set up yet (see the ctor
1550b57cec5SDimitry Andric   // where the byte order is setfrom the process).  If that's the case, we
1560b57cec5SDimitry Andric   // can't set the value here.
1570b57cec5SDimitry Andric   if (m_reg_data.GetByteOrder() == eByteOrderInvalid) {
1580b57cec5SDimitry Andric     return false;
1590b57cec5SDimitry Andric   }
1600b57cec5SDimitry Andric 
1610b57cec5SDimitry Andric   // Invalidate if needed
1620b57cec5SDimitry Andric   InvalidateIfNeeded(false);
1630b57cec5SDimitry Andric 
1640b57cec5SDimitry Andric   DataBufferSP buffer_sp(new DataBufferHeap(&new_reg_val, sizeof(new_reg_val)));
1650b57cec5SDimitry Andric   DataExtractor data(buffer_sp, endian::InlHostByteOrder(), sizeof(void *));
1660b57cec5SDimitry Andric 
1670b57cec5SDimitry Andric   // If our register context and our register info disagree, which should never
1680b57cec5SDimitry Andric   // happen, don't overwrite past the end of the buffer.
1690b57cec5SDimitry Andric   if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
1700b57cec5SDimitry Andric     return false;
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   // Grab a pointer to where we are going to put this register
1730b57cec5SDimitry Andric   uint8_t *dst = const_cast<uint8_t *>(
1740b57cec5SDimitry Andric       m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
1750b57cec5SDimitry Andric 
1760b57cec5SDimitry Andric   if (dst == nullptr)
1770b57cec5SDimitry Andric     return false;
1780b57cec5SDimitry Andric 
1790b57cec5SDimitry Andric   if (data.CopyByteOrderedData(0,                          // src offset
1800b57cec5SDimitry Andric                                reg_info->byte_size,        // src length
1810b57cec5SDimitry Andric                                dst,                        // dst
1820b57cec5SDimitry Andric                                reg_info->byte_size,        // dst length
1830b57cec5SDimitry Andric                                m_reg_data.GetByteOrder())) // dst byte order
1840b57cec5SDimitry Andric   {
1850b57cec5SDimitry Andric     SetRegisterIsValid(reg, true);
1860b57cec5SDimitry Andric     return true;
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric   return false;
1890b57cec5SDimitry Andric }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric // Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().
GetPrimordialRegister(const RegisterInfo * reg_info,GDBRemoteCommunicationClient & gdb_comm)1920b57cec5SDimitry Andric bool GDBRemoteRegisterContext::GetPrimordialRegister(
1930b57cec5SDimitry Andric     const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) {
1940b57cec5SDimitry Andric   const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB];
1950b57cec5SDimitry Andric   const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin];
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   if (DataBufferSP buffer_sp =
1980b57cec5SDimitry Andric           gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg))
1990b57cec5SDimitry Andric     return PrivateSetRegisterValue(
2000b57cec5SDimitry Andric         lldb_reg, llvm::ArrayRef<uint8_t>(buffer_sp->GetBytes(),
2010b57cec5SDimitry Andric                                           buffer_sp->GetByteSize()));
2020b57cec5SDimitry Andric   return false;
2030b57cec5SDimitry Andric }
2040b57cec5SDimitry Andric 
ReadRegisterBytes(const RegisterInfo * reg_info)205349cc55cSDimitry Andric bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info) {
2060b57cec5SDimitry Andric   ExecutionContext exe_ctx(CalculateThread());
2070b57cec5SDimitry Andric 
2080b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
2090b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
2100b57cec5SDimitry Andric   if (process == nullptr || thread == nullptr)
2110b57cec5SDimitry Andric     return false;
2120b57cec5SDimitry Andric 
2130b57cec5SDimitry Andric   GDBRemoteCommunicationClient &gdb_comm(
2140b57cec5SDimitry Andric       ((ProcessGDBRemote *)process)->GetGDBRemote());
2150b57cec5SDimitry Andric 
2160b57cec5SDimitry Andric   InvalidateIfNeeded(false);
2170b57cec5SDimitry Andric 
2180b57cec5SDimitry Andric   const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
2190b57cec5SDimitry Andric 
2200b57cec5SDimitry Andric   if (!GetRegisterIsValid(reg)) {
221fe6060f1SDimitry Andric     if (m_read_all_at_once && !m_gpacket_cached) {
2220b57cec5SDimitry Andric       if (DataBufferSP buffer_sp =
2230b57cec5SDimitry Andric               gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) {
2240b57cec5SDimitry Andric         memcpy(const_cast<uint8_t *>(m_reg_data.GetDataStart()),
2250b57cec5SDimitry Andric                buffer_sp->GetBytes(),
2260b57cec5SDimitry Andric                std::min(buffer_sp->GetByteSize(), m_reg_data.GetByteSize()));
2270b57cec5SDimitry Andric         if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize()) {
2280b57cec5SDimitry Andric           SetAllRegisterValid(true);
2290b57cec5SDimitry Andric           return true;
230480093f4SDimitry Andric         } else if (buffer_sp->GetByteSize() > 0) {
231*5f757f3fSDimitry Andric           for (auto x : llvm::enumerate(
232*5f757f3fSDimitry Andric                    m_reg_info_sp->registers<
233*5f757f3fSDimitry Andric                        DynamicRegisterInfo::reg_collection_const_range>())) {
234349cc55cSDimitry Andric             const struct RegisterInfo &reginfo = x.value();
235349cc55cSDimitry Andric             m_reg_valid[x.index()] =
236349cc55cSDimitry Andric                 (reginfo.byte_offset + reginfo.byte_size <=
237349cc55cSDimitry Andric                  buffer_sp->GetByteSize());
238480093f4SDimitry Andric           }
239fe6060f1SDimitry Andric 
240fe6060f1SDimitry Andric           m_gpacket_cached = true;
241fe6060f1SDimitry Andric           if (GetRegisterIsValid(reg))
242480093f4SDimitry Andric             return true;
2430b57cec5SDimitry Andric         } else {
2441fd87a68SDimitry Andric           Log *log(GetLog(GDBRLog::Thread | GDBRLog::Packets));
2459dba64beSDimitry Andric           LLDB_LOGF(
2469dba64beSDimitry Andric               log,
2479dba64beSDimitry Andric               "error: GDBRemoteRegisterContext::ReadRegisterBytes tried "
2489dba64beSDimitry Andric               "to read the "
2499dba64beSDimitry Andric               "entire register context at once, expected at least %" PRId64
2509dba64beSDimitry Andric               " bytes "
2519dba64beSDimitry Andric               "but only got %" PRId64 " bytes.",
2529dba64beSDimitry Andric               m_reg_data.GetByteSize(), buffer_sp->GetByteSize());
2530b57cec5SDimitry Andric           return false;
2540b57cec5SDimitry Andric         }
255fe6060f1SDimitry Andric       }
256fe6060f1SDimitry Andric     }
2570b57cec5SDimitry Andric     if (reg_info->value_regs) {
2580b57cec5SDimitry Andric       // Process this composite register request by delegating to the
2590b57cec5SDimitry Andric       // constituent primordial registers.
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric       // Index of the primordial register.
2620b57cec5SDimitry Andric       bool success = true;
2630b57cec5SDimitry Andric       for (uint32_t idx = 0; success; ++idx) {
2640b57cec5SDimitry Andric         const uint32_t prim_reg = reg_info->value_regs[idx];
2650b57cec5SDimitry Andric         if (prim_reg == LLDB_INVALID_REGNUM)
2660b57cec5SDimitry Andric           break;
2670b57cec5SDimitry Andric         // We have a valid primordial register as our constituent. Grab the
2680b57cec5SDimitry Andric         // corresponding register info.
269fe6060f1SDimitry Andric         const RegisterInfo *prim_reg_info =
270349cc55cSDimitry Andric             GetRegisterInfo(eRegisterKindLLDB, prim_reg);
2710b57cec5SDimitry Andric         if (prim_reg_info == nullptr)
2720b57cec5SDimitry Andric           success = false;
2730b57cec5SDimitry Andric         else {
2740b57cec5SDimitry Andric           // Read the containing register if it hasn't already been read
2750b57cec5SDimitry Andric           if (!GetRegisterIsValid(prim_reg))
2760b57cec5SDimitry Andric             success = GetPrimordialRegister(prim_reg_info, gdb_comm);
2770b57cec5SDimitry Andric         }
2780b57cec5SDimitry Andric       }
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric       if (success) {
2810b57cec5SDimitry Andric         // If we reach this point, all primordial register requests have
2820b57cec5SDimitry Andric         // succeeded. Validate this composite register.
2830b57cec5SDimitry Andric         SetRegisterIsValid(reg_info, true);
2840b57cec5SDimitry Andric       }
2850b57cec5SDimitry Andric     } else {
2860b57cec5SDimitry Andric       // Get each register individually
2870b57cec5SDimitry Andric       GetPrimordialRegister(reg_info, gdb_comm);
2880b57cec5SDimitry Andric     }
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric     // Make sure we got a valid register value after reading it
2910b57cec5SDimitry Andric     if (!GetRegisterIsValid(reg))
2920b57cec5SDimitry Andric       return false;
2930b57cec5SDimitry Andric   }
2940b57cec5SDimitry Andric 
2950b57cec5SDimitry Andric   return true;
2960b57cec5SDimitry Andric }
2970b57cec5SDimitry Andric 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & value)2980b57cec5SDimitry Andric bool GDBRemoteRegisterContext::WriteRegister(const RegisterInfo *reg_info,
2990b57cec5SDimitry Andric                                              const RegisterValue &value) {
3000b57cec5SDimitry Andric   DataExtractor data;
301349cc55cSDimitry Andric   if (value.GetData(data)) {
302349cc55cSDimitry Andric     if (reg_info->value_regs &&
303349cc55cSDimitry Andric         reg_info->value_regs[0] != LLDB_INVALID_REGNUM &&
304349cc55cSDimitry Andric         reg_info->value_regs[1] != LLDB_INVALID_REGNUM) {
305349cc55cSDimitry Andric       uint32_t combined_size = 0;
306349cc55cSDimitry Andric       for (int i = 0; reg_info->value_regs[i] != LLDB_INVALID_REGNUM; i++) {
307349cc55cSDimitry Andric         const RegisterInfo *parent_reg = GetRegisterInfo(
308349cc55cSDimitry Andric             eRegisterKindLLDB, reg_info->value_regs[i]);
309349cc55cSDimitry Andric         if (!parent_reg)
310349cc55cSDimitry Andric           return false;
311349cc55cSDimitry Andric         combined_size += parent_reg->byte_size;
312349cc55cSDimitry Andric       }
313349cc55cSDimitry Andric 
314349cc55cSDimitry Andric       if (data.GetByteSize() < combined_size)
315349cc55cSDimitry Andric         return false;
316349cc55cSDimitry Andric 
317349cc55cSDimitry Andric       uint32_t offset = 0;
318349cc55cSDimitry Andric       for (int i = 0; reg_info->value_regs[i] != LLDB_INVALID_REGNUM; i++) {
319349cc55cSDimitry Andric         const RegisterInfo *parent_reg = GetRegisterInfo(
320349cc55cSDimitry Andric             eRegisterKindLLDB, reg_info->value_regs[i]);
321349cc55cSDimitry Andric         assert(parent_reg);
322349cc55cSDimitry Andric 
323349cc55cSDimitry Andric         DataExtractor parent_data{data, offset, parent_reg->byte_size};
324349cc55cSDimitry Andric         if (!WriteRegisterBytes(parent_reg, parent_data, 0))
325349cc55cSDimitry Andric           return false;
326349cc55cSDimitry Andric         offset += parent_reg->byte_size;
327349cc55cSDimitry Andric       }
328349cc55cSDimitry Andric       assert(offset == combined_size);
329349cc55cSDimitry Andric       return true;
330349cc55cSDimitry Andric     } else
3310b57cec5SDimitry Andric       return WriteRegisterBytes(reg_info, data, 0);
332349cc55cSDimitry Andric   }
3330b57cec5SDimitry Andric   return false;
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
3360b57cec5SDimitry Andric // Helper function for GDBRemoteRegisterContext::WriteRegisterBytes().
SetPrimordialRegister(const RegisterInfo * reg_info,GDBRemoteCommunicationClient & gdb_comm)3370b57cec5SDimitry Andric bool GDBRemoteRegisterContext::SetPrimordialRegister(
3380b57cec5SDimitry Andric     const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) {
3390b57cec5SDimitry Andric   StreamString packet;
3400b57cec5SDimitry Andric   StringExtractorGDBRemote response;
3410b57cec5SDimitry Andric   const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
3420b57cec5SDimitry Andric   // Invalidate just this register
3430b57cec5SDimitry Andric   SetRegisterIsValid(reg, false);
3440b57cec5SDimitry Andric 
3450b57cec5SDimitry Andric   return gdb_comm.WriteRegister(
3460b57cec5SDimitry Andric       m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin],
3470b57cec5SDimitry Andric       {m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
3480b57cec5SDimitry Andric        reg_info->byte_size});
3490b57cec5SDimitry Andric }
3500b57cec5SDimitry Andric 
WriteRegisterBytes(const RegisterInfo * reg_info,DataExtractor & data,uint32_t data_offset)3510b57cec5SDimitry Andric bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
3520b57cec5SDimitry Andric                                                   DataExtractor &data,
3530b57cec5SDimitry Andric                                                   uint32_t data_offset) {
3540b57cec5SDimitry Andric   ExecutionContext exe_ctx(CalculateThread());
3550b57cec5SDimitry Andric 
3560b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
3570b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
3580b57cec5SDimitry Andric   if (process == nullptr || thread == nullptr)
3590b57cec5SDimitry Andric     return false;
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   GDBRemoteCommunicationClient &gdb_comm(
3620b57cec5SDimitry Andric       ((ProcessGDBRemote *)process)->GetGDBRemote());
3630b57cec5SDimitry Andric 
3640b57cec5SDimitry Andric   assert(m_reg_data.GetByteSize() >=
3650b57cec5SDimitry Andric          reg_info->byte_offset + reg_info->byte_size);
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric   // If our register context and our register info disagree, which should never
3680b57cec5SDimitry Andric   // happen, don't overwrite past the end of the buffer.
3690b57cec5SDimitry Andric   if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
3700b57cec5SDimitry Andric     return false;
3710b57cec5SDimitry Andric 
3720b57cec5SDimitry Andric   // Grab a pointer to where we are going to put this register
3730b57cec5SDimitry Andric   uint8_t *dst = const_cast<uint8_t *>(
3740b57cec5SDimitry Andric       m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
3750b57cec5SDimitry Andric 
3760b57cec5SDimitry Andric   if (dst == nullptr)
3770b57cec5SDimitry Andric     return false;
3780b57cec5SDimitry Andric 
379*5f757f3fSDimitry Andric   const bool should_reconfigure_registers =
380*5f757f3fSDimitry Andric       RegisterWriteCausesReconfigure(reg_info->name);
381e8d8bef9SDimitry Andric 
3820b57cec5SDimitry Andric   if (data.CopyByteOrderedData(data_offset,                // src offset
3830b57cec5SDimitry Andric                                reg_info->byte_size,        // src length
3840b57cec5SDimitry Andric                                dst,                        // dst
3850b57cec5SDimitry Andric                                reg_info->byte_size,        // dst length
3860b57cec5SDimitry Andric                                m_reg_data.GetByteOrder())) // dst byte order
3870b57cec5SDimitry Andric   {
388fe6060f1SDimitry Andric     GDBRemoteClientBase::Lock lock(gdb_comm);
3890b57cec5SDimitry Andric     if (lock) {
390480093f4SDimitry Andric       if (m_write_all_at_once) {
3910b57cec5SDimitry Andric         // Invalidate all register values
3920b57cec5SDimitry Andric         InvalidateIfNeeded(true);
3930b57cec5SDimitry Andric 
3940b57cec5SDimitry Andric         // Set all registers in one packet
3950b57cec5SDimitry Andric         if (gdb_comm.WriteAllRegisters(
3960b57cec5SDimitry Andric                 m_thread.GetProtocolID(),
3970b57cec5SDimitry Andric                 {m_reg_data.GetDataStart(), size_t(m_reg_data.GetByteSize())}))
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric         {
400*5f757f3fSDimitry Andric           if (should_reconfigure_registers)
401*5f757f3fSDimitry Andric             ReconfigureRegisterInfo();
402e8d8bef9SDimitry Andric 
403*5f757f3fSDimitry Andric           InvalidateAllRegisters();
404e8d8bef9SDimitry Andric 
4050b57cec5SDimitry Andric           return true;
4060b57cec5SDimitry Andric         }
4070b57cec5SDimitry Andric       } else {
4080b57cec5SDimitry Andric         bool success = true;
4090b57cec5SDimitry Andric 
4100b57cec5SDimitry Andric         if (reg_info->value_regs) {
4110b57cec5SDimitry Andric           // This register is part of another register. In this case we read
4120b57cec5SDimitry Andric           // the actual register data for any "value_regs", and once all that
4130b57cec5SDimitry Andric           // data is read, we will have enough data in our register context
4140b57cec5SDimitry Andric           // bytes for the value of this register
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric           // Invalidate this composite register first.
4170b57cec5SDimitry Andric 
4180b57cec5SDimitry Andric           for (uint32_t idx = 0; success; ++idx) {
4190b57cec5SDimitry Andric             const uint32_t reg = reg_info->value_regs[idx];
4200b57cec5SDimitry Andric             if (reg == LLDB_INVALID_REGNUM)
4210b57cec5SDimitry Andric               break;
4220b57cec5SDimitry Andric             // We have a valid primordial register as our constituent. Grab the
4230b57cec5SDimitry Andric             // corresponding register info.
424fe6060f1SDimitry Andric             const RegisterInfo *value_reg_info =
425349cc55cSDimitry Andric                 GetRegisterInfo(eRegisterKindLLDB, reg);
4260b57cec5SDimitry Andric             if (value_reg_info == nullptr)
4270b57cec5SDimitry Andric               success = false;
4280b57cec5SDimitry Andric             else
4290b57cec5SDimitry Andric               success = SetPrimordialRegister(value_reg_info, gdb_comm);
4300b57cec5SDimitry Andric           }
4310b57cec5SDimitry Andric         } else {
4320b57cec5SDimitry Andric           // This is an actual register, write it
4330b57cec5SDimitry Andric           success = SetPrimordialRegister(reg_info, gdb_comm);
4340b57cec5SDimitry Andric         }
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric         // Check if writing this register will invalidate any other register
4370b57cec5SDimitry Andric         // values? If so, invalidate them
4380b57cec5SDimitry Andric         if (reg_info->invalidate_regs) {
4390b57cec5SDimitry Andric           for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
4400b57cec5SDimitry Andric                reg != LLDB_INVALID_REGNUM;
441fe6060f1SDimitry Andric                reg = reg_info->invalidate_regs[++idx])
442fe6060f1SDimitry Andric             SetRegisterIsValid(ConvertRegisterKindToRegisterNumber(
443349cc55cSDimitry Andric                                    eRegisterKindLLDB, reg),
444fe6060f1SDimitry Andric                                false);
4450b57cec5SDimitry Andric         }
4460b57cec5SDimitry Andric 
447*5f757f3fSDimitry Andric         if (success && should_reconfigure_registers &&
448*5f757f3fSDimitry Andric             ReconfigureRegisterInfo())
449*5f757f3fSDimitry Andric           InvalidateAllRegisters();
450*5f757f3fSDimitry Andric 
4510b57cec5SDimitry Andric         return success;
4520b57cec5SDimitry Andric       }
4530b57cec5SDimitry Andric     } else {
4541fd87a68SDimitry Andric       Log *log(GetLog(GDBRLog::Thread | GDBRLog::Packets));
4550b57cec5SDimitry Andric       if (log) {
4560b57cec5SDimitry Andric         if (log->GetVerbose()) {
4570b57cec5SDimitry Andric           StreamString strm;
45806c3fb27SDimitry Andric           process->DumpPluginHistory(strm);
4599dba64beSDimitry Andric           LLDB_LOGF(log,
4609dba64beSDimitry Andric                     "error: failed to get packet sequence mutex, not sending "
4610b57cec5SDimitry Andric                     "write register for \"%s\":\n%s",
4620b57cec5SDimitry Andric                     reg_info->name, strm.GetData());
4630b57cec5SDimitry Andric         } else
4649dba64beSDimitry Andric           LLDB_LOGF(log,
4659dba64beSDimitry Andric                     "error: failed to get packet sequence mutex, not sending "
4660b57cec5SDimitry Andric                     "write register for \"%s\"",
4670b57cec5SDimitry Andric                     reg_info->name);
4680b57cec5SDimitry Andric       }
4690b57cec5SDimitry Andric     }
4700b57cec5SDimitry Andric   }
4710b57cec5SDimitry Andric   return false;
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric 
ReadAllRegisterValues(RegisterCheckpoint & reg_checkpoint)4740b57cec5SDimitry Andric bool GDBRemoteRegisterContext::ReadAllRegisterValues(
4750b57cec5SDimitry Andric     RegisterCheckpoint &reg_checkpoint) {
4760b57cec5SDimitry Andric   ExecutionContext exe_ctx(CalculateThread());
4770b57cec5SDimitry Andric 
4780b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
4790b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
4800b57cec5SDimitry Andric   if (process == nullptr || thread == nullptr)
4810b57cec5SDimitry Andric     return false;
4820b57cec5SDimitry Andric 
4830b57cec5SDimitry Andric   GDBRemoteCommunicationClient &gdb_comm(
4840b57cec5SDimitry Andric       ((ProcessGDBRemote *)process)->GetGDBRemote());
4850b57cec5SDimitry Andric 
4860b57cec5SDimitry Andric   uint32_t save_id = 0;
4870b57cec5SDimitry Andric   if (gdb_comm.SaveRegisterState(thread->GetProtocolID(), save_id)) {
4880b57cec5SDimitry Andric     reg_checkpoint.SetID(save_id);
4890b57cec5SDimitry Andric     reg_checkpoint.GetData().reset();
4900b57cec5SDimitry Andric     return true;
4910b57cec5SDimitry Andric   } else {
4920b57cec5SDimitry Andric     reg_checkpoint.SetID(0); // Invalid save ID is zero
4930b57cec5SDimitry Andric     return ReadAllRegisterValues(reg_checkpoint.GetData());
4940b57cec5SDimitry Andric   }
4950b57cec5SDimitry Andric }
4960b57cec5SDimitry Andric 
WriteAllRegisterValues(const RegisterCheckpoint & reg_checkpoint)4970b57cec5SDimitry Andric bool GDBRemoteRegisterContext::WriteAllRegisterValues(
4980b57cec5SDimitry Andric     const RegisterCheckpoint &reg_checkpoint) {
4990b57cec5SDimitry Andric   uint32_t save_id = reg_checkpoint.GetID();
5000b57cec5SDimitry Andric   if (save_id != 0) {
5010b57cec5SDimitry Andric     ExecutionContext exe_ctx(CalculateThread());
5020b57cec5SDimitry Andric 
5030b57cec5SDimitry Andric     Process *process = exe_ctx.GetProcessPtr();
5040b57cec5SDimitry Andric     Thread *thread = exe_ctx.GetThreadPtr();
5050b57cec5SDimitry Andric     if (process == nullptr || thread == nullptr)
5060b57cec5SDimitry Andric       return false;
5070b57cec5SDimitry Andric 
5080b57cec5SDimitry Andric     GDBRemoteCommunicationClient &gdb_comm(
5090b57cec5SDimitry Andric         ((ProcessGDBRemote *)process)->GetGDBRemote());
5100b57cec5SDimitry Andric 
5110b57cec5SDimitry Andric     return gdb_comm.RestoreRegisterState(m_thread.GetProtocolID(), save_id);
5120b57cec5SDimitry Andric   } else {
5130b57cec5SDimitry Andric     return WriteAllRegisterValues(reg_checkpoint.GetData());
5140b57cec5SDimitry Andric   }
5150b57cec5SDimitry Andric }
5160b57cec5SDimitry Andric 
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)5170b57cec5SDimitry Andric bool GDBRemoteRegisterContext::ReadAllRegisterValues(
51881ad6265SDimitry Andric     lldb::WritableDataBufferSP &data_sp) {
5190b57cec5SDimitry Andric   ExecutionContext exe_ctx(CalculateThread());
5200b57cec5SDimitry Andric 
5210b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
5220b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
5230b57cec5SDimitry Andric   if (process == nullptr || thread == nullptr)
5240b57cec5SDimitry Andric     return false;
5250b57cec5SDimitry Andric 
5260b57cec5SDimitry Andric   GDBRemoteCommunicationClient &gdb_comm(
5270b57cec5SDimitry Andric       ((ProcessGDBRemote *)process)->GetGDBRemote());
5280b57cec5SDimitry Andric 
5290b57cec5SDimitry Andric   const bool use_g_packet =
5300b57cec5SDimitry Andric       !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);
5310b57cec5SDimitry Andric 
532fe6060f1SDimitry Andric   GDBRemoteClientBase::Lock lock(gdb_comm);
5330b57cec5SDimitry Andric   if (lock) {
5340b57cec5SDimitry Andric     if (gdb_comm.SyncThreadState(m_thread.GetProtocolID()))
5350b57cec5SDimitry Andric       InvalidateAllRegisters();
5360b57cec5SDimitry Andric 
53781ad6265SDimitry Andric     if (use_g_packet) {
53881ad6265SDimitry Andric       if (DataBufferSP data_buffer =
53981ad6265SDimitry Andric               gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) {
54081ad6265SDimitry Andric         data_sp = std::make_shared<DataBufferHeap>(*data_buffer);
5410b57cec5SDimitry Andric         return true;
54281ad6265SDimitry Andric       }
54381ad6265SDimitry Andric     }
5440b57cec5SDimitry Andric 
5450b57cec5SDimitry Andric     // We're going to read each register
5460b57cec5SDimitry Andric     // individually and store them as binary data in a buffer.
5470b57cec5SDimitry Andric     const RegisterInfo *reg_info;
5480b57cec5SDimitry Andric 
5490b57cec5SDimitry Andric     for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != nullptr;
5500b57cec5SDimitry Andric          i++) {
5510b57cec5SDimitry Andric       if (reg_info
5520b57cec5SDimitry Andric               ->value_regs) // skip registers that are slices of real registers
5530b57cec5SDimitry Andric         continue;
554349cc55cSDimitry Andric       ReadRegisterBytes(reg_info);
5550b57cec5SDimitry Andric       // ReadRegisterBytes saves the contents of the register in to the
5560b57cec5SDimitry Andric       // m_reg_data buffer
5570b57cec5SDimitry Andric     }
5580b57cec5SDimitry Andric     data_sp = std::make_shared<DataBufferHeap>(
559e8d8bef9SDimitry Andric         m_reg_data.GetDataStart(), m_reg_info_sp->GetRegisterDataByteSize());
5600b57cec5SDimitry Andric     return true;
5610b57cec5SDimitry Andric   } else {
5620b57cec5SDimitry Andric 
5631fd87a68SDimitry Andric     Log *log(GetLog(GDBRLog::Thread | GDBRLog::Packets));
5640b57cec5SDimitry Andric     if (log) {
5650b57cec5SDimitry Andric       if (log->GetVerbose()) {
5660b57cec5SDimitry Andric         StreamString strm;
56706c3fb27SDimitry Andric         process->DumpPluginHistory(strm);
5689dba64beSDimitry Andric         LLDB_LOGF(log,
5699dba64beSDimitry Andric                   "error: failed to get packet sequence mutex, not sending "
5700b57cec5SDimitry Andric                   "read all registers:\n%s",
5710b57cec5SDimitry Andric                   strm.GetData());
5720b57cec5SDimitry Andric       } else
5739dba64beSDimitry Andric         LLDB_LOGF(log,
5749dba64beSDimitry Andric                   "error: failed to get packet sequence mutex, not sending "
5750b57cec5SDimitry Andric                   "read all registers");
5760b57cec5SDimitry Andric     }
5770b57cec5SDimitry Andric   }
5780b57cec5SDimitry Andric 
5790b57cec5SDimitry Andric   data_sp.reset();
5800b57cec5SDimitry Andric   return false;
5810b57cec5SDimitry Andric }
5820b57cec5SDimitry Andric 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)5830b57cec5SDimitry Andric bool GDBRemoteRegisterContext::WriteAllRegisterValues(
5840b57cec5SDimitry Andric     const lldb::DataBufferSP &data_sp) {
5850b57cec5SDimitry Andric   if (!data_sp || data_sp->GetBytes() == nullptr || data_sp->GetByteSize() == 0)
5860b57cec5SDimitry Andric     return false;
5870b57cec5SDimitry Andric 
5880b57cec5SDimitry Andric   ExecutionContext exe_ctx(CalculateThread());
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
5910b57cec5SDimitry Andric   Thread *thread = exe_ctx.GetThreadPtr();
5920b57cec5SDimitry Andric   if (process == nullptr || thread == nullptr)
5930b57cec5SDimitry Andric     return false;
5940b57cec5SDimitry Andric 
5950b57cec5SDimitry Andric   GDBRemoteCommunicationClient &gdb_comm(
5960b57cec5SDimitry Andric       ((ProcessGDBRemote *)process)->GetGDBRemote());
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric   const bool use_g_packet =
5990b57cec5SDimitry Andric       !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);
6000b57cec5SDimitry Andric 
601fe6060f1SDimitry Andric   GDBRemoteClientBase::Lock lock(gdb_comm);
6020b57cec5SDimitry Andric   if (lock) {
6030b57cec5SDimitry Andric     // The data_sp contains the G response packet.
6040b57cec5SDimitry Andric     if (use_g_packet) {
6050b57cec5SDimitry Andric       if (gdb_comm.WriteAllRegisters(
6060b57cec5SDimitry Andric               m_thread.GetProtocolID(),
6070b57cec5SDimitry Andric               {data_sp->GetBytes(), size_t(data_sp->GetByteSize())}))
6080b57cec5SDimitry Andric         return true;
6090b57cec5SDimitry Andric 
6100b57cec5SDimitry Andric       uint32_t num_restored = 0;
6110b57cec5SDimitry Andric       // We need to manually go through all of the registers and restore them
6120b57cec5SDimitry Andric       // manually
6130b57cec5SDimitry Andric       DataExtractor restore_data(data_sp, m_reg_data.GetByteOrder(),
6140b57cec5SDimitry Andric                                  m_reg_data.GetAddressByteSize());
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric       const RegisterInfo *reg_info;
6170b57cec5SDimitry Andric 
6180b57cec5SDimitry Andric       // The g packet contents may either include the slice registers
6190b57cec5SDimitry Andric       // (registers defined in terms of other registers, e.g. eax is a subset
6200b57cec5SDimitry Andric       // of rax) or not.  The slice registers should NOT be in the g packet,
6210b57cec5SDimitry Andric       // but some implementations may incorrectly include them.
6220b57cec5SDimitry Andric       //
6230b57cec5SDimitry Andric       // If the slice registers are included in the packet, we must step over
6240b57cec5SDimitry Andric       // the slice registers when parsing the packet -- relying on the
6250b57cec5SDimitry Andric       // RegisterInfo byte_offset field would be incorrect. If the slice
6260b57cec5SDimitry Andric       // registers are not included, then using the byte_offset values into the
6270b57cec5SDimitry Andric       // data buffer is the best way to find individual register values.
6280b57cec5SDimitry Andric 
6290b57cec5SDimitry Andric       uint64_t size_including_slice_registers = 0;
6300b57cec5SDimitry Andric       uint64_t size_not_including_slice_registers = 0;
6310b57cec5SDimitry Andric       uint64_t size_by_highest_offset = 0;
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric       for (uint32_t reg_idx = 0;
6340b57cec5SDimitry Andric            (reg_info = GetRegisterInfoAtIndex(reg_idx)) != nullptr; ++reg_idx) {
6350b57cec5SDimitry Andric         size_including_slice_registers += reg_info->byte_size;
6360b57cec5SDimitry Andric         if (reg_info->value_regs == nullptr)
6370b57cec5SDimitry Andric           size_not_including_slice_registers += reg_info->byte_size;
6380b57cec5SDimitry Andric         if (reg_info->byte_offset >= size_by_highest_offset)
6390b57cec5SDimitry Andric           size_by_highest_offset = reg_info->byte_offset + reg_info->byte_size;
6400b57cec5SDimitry Andric       }
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric       bool use_byte_offset_into_buffer;
6430b57cec5SDimitry Andric       if (size_by_highest_offset == restore_data.GetByteSize()) {
6440b57cec5SDimitry Andric         // The size of the packet agrees with the highest offset: + size in the
6450b57cec5SDimitry Andric         // register file
6460b57cec5SDimitry Andric         use_byte_offset_into_buffer = true;
6470b57cec5SDimitry Andric       } else if (size_not_including_slice_registers ==
6480b57cec5SDimitry Andric                  restore_data.GetByteSize()) {
6490b57cec5SDimitry Andric         // The size of the packet is the same as concatenating all of the
6500b57cec5SDimitry Andric         // registers sequentially, skipping the slice registers
6510b57cec5SDimitry Andric         use_byte_offset_into_buffer = true;
6520b57cec5SDimitry Andric       } else if (size_including_slice_registers == restore_data.GetByteSize()) {
6530b57cec5SDimitry Andric         // The slice registers are present in the packet (when they shouldn't
6540b57cec5SDimitry Andric         // be). Don't try to use the RegisterInfo byte_offset into the
6550b57cec5SDimitry Andric         // restore_data, it will point to the wrong place.
6560b57cec5SDimitry Andric         use_byte_offset_into_buffer = false;
6570b57cec5SDimitry Andric       } else {
6580b57cec5SDimitry Andric         // None of our expected sizes match the actual g packet data we're
6590b57cec5SDimitry Andric         // looking at. The most conservative approach here is to use the
6600b57cec5SDimitry Andric         // running total byte offset.
6610b57cec5SDimitry Andric         use_byte_offset_into_buffer = false;
6620b57cec5SDimitry Andric       }
6630b57cec5SDimitry Andric 
6640b57cec5SDimitry Andric       // In case our register definitions don't include the correct offsets,
6650b57cec5SDimitry Andric       // keep track of the size of each reg & compute offset based on that.
6660b57cec5SDimitry Andric       uint32_t running_byte_offset = 0;
6670b57cec5SDimitry Andric       for (uint32_t reg_idx = 0;
6680b57cec5SDimitry Andric            (reg_info = GetRegisterInfoAtIndex(reg_idx)) != nullptr;
6690b57cec5SDimitry Andric            ++reg_idx, running_byte_offset += reg_info->byte_size) {
6700b57cec5SDimitry Andric         // Skip composite aka slice registers (e.g. eax is a slice of rax).
6710b57cec5SDimitry Andric         if (reg_info->value_regs)
6720b57cec5SDimitry Andric           continue;
6730b57cec5SDimitry Andric 
6740b57cec5SDimitry Andric         const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
6750b57cec5SDimitry Andric 
6760b57cec5SDimitry Andric         uint32_t register_offset;
6770b57cec5SDimitry Andric         if (use_byte_offset_into_buffer) {
6780b57cec5SDimitry Andric           register_offset = reg_info->byte_offset;
6790b57cec5SDimitry Andric         } else {
6800b57cec5SDimitry Andric           register_offset = running_byte_offset;
6810b57cec5SDimitry Andric         }
6820b57cec5SDimitry Andric 
6830b57cec5SDimitry Andric         const uint32_t reg_byte_size = reg_info->byte_size;
6840b57cec5SDimitry Andric 
6850b57cec5SDimitry Andric         const uint8_t *restore_src =
6860b57cec5SDimitry Andric             restore_data.PeekData(register_offset, reg_byte_size);
6870b57cec5SDimitry Andric         if (restore_src) {
6880b57cec5SDimitry Andric           SetRegisterIsValid(reg, false);
6890b57cec5SDimitry Andric           if (gdb_comm.WriteRegister(
6900b57cec5SDimitry Andric                   m_thread.GetProtocolID(),
6910b57cec5SDimitry Andric                   reg_info->kinds[eRegisterKindProcessPlugin],
6920b57cec5SDimitry Andric                   {restore_src, reg_byte_size}))
6930b57cec5SDimitry Andric             ++num_restored;
6940b57cec5SDimitry Andric         }
6950b57cec5SDimitry Andric       }
6960b57cec5SDimitry Andric       return num_restored > 0;
6970b57cec5SDimitry Andric     } else {
6980b57cec5SDimitry Andric       // For the use_g_packet == false case, we're going to write each register
6990b57cec5SDimitry Andric       // individually.  The data buffer is binary data in this case, instead of
7000b57cec5SDimitry Andric       // ascii characters.
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric       bool arm64_debugserver = false;
7030b57cec5SDimitry Andric       if (m_thread.GetProcess().get()) {
7040b57cec5SDimitry Andric         const ArchSpec &arch =
7050b57cec5SDimitry Andric             m_thread.GetProcess()->GetTarget().GetArchitecture();
706e8d8bef9SDimitry Andric         if (arch.IsValid() && (arch.GetMachine() == llvm::Triple::aarch64 ||
7079dba64beSDimitry Andric                                arch.GetMachine() == llvm::Triple::aarch64_32) &&
7080b57cec5SDimitry Andric             arch.GetTriple().getVendor() == llvm::Triple::Apple &&
7090b57cec5SDimitry Andric             arch.GetTriple().getOS() == llvm::Triple::IOS) {
7100b57cec5SDimitry Andric           arm64_debugserver = true;
7110b57cec5SDimitry Andric         }
7120b57cec5SDimitry Andric       }
7130b57cec5SDimitry Andric       uint32_t num_restored = 0;
7140b57cec5SDimitry Andric       const RegisterInfo *reg_info;
7150b57cec5SDimitry Andric       for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != nullptr;
7160b57cec5SDimitry Andric            i++) {
7170b57cec5SDimitry Andric         if (reg_info->value_regs) // skip registers that are slices of real
7180b57cec5SDimitry Andric                                   // registers
7190b57cec5SDimitry Andric           continue;
7200b57cec5SDimitry Andric         // Skip the fpsr and fpcr floating point status/control register
7210b57cec5SDimitry Andric         // writing to work around a bug in an older version of debugserver that
7220b57cec5SDimitry Andric         // would lead to register context corruption when writing fpsr/fpcr.
7230b57cec5SDimitry Andric         if (arm64_debugserver && (strcmp(reg_info->name, "fpsr") == 0 ||
7240b57cec5SDimitry Andric                                   strcmp(reg_info->name, "fpcr") == 0)) {
7250b57cec5SDimitry Andric           continue;
7260b57cec5SDimitry Andric         }
7270b57cec5SDimitry Andric 
7280b57cec5SDimitry Andric         SetRegisterIsValid(reg_info, false);
7290b57cec5SDimitry Andric         if (gdb_comm.WriteRegister(m_thread.GetProtocolID(),
7300b57cec5SDimitry Andric                                    reg_info->kinds[eRegisterKindProcessPlugin],
7310b57cec5SDimitry Andric                                    {data_sp->GetBytes() + reg_info->byte_offset,
7320b57cec5SDimitry Andric                                     reg_info->byte_size}))
7330b57cec5SDimitry Andric           ++num_restored;
7340b57cec5SDimitry Andric       }
7350b57cec5SDimitry Andric       return num_restored > 0;
7360b57cec5SDimitry Andric     }
7370b57cec5SDimitry Andric   } else {
7381fd87a68SDimitry Andric     Log *log(GetLog(GDBRLog::Thread | GDBRLog::Packets));
7390b57cec5SDimitry Andric     if (log) {
7400b57cec5SDimitry Andric       if (log->GetVerbose()) {
7410b57cec5SDimitry Andric         StreamString strm;
74206c3fb27SDimitry Andric         process->DumpPluginHistory(strm);
7439dba64beSDimitry Andric         LLDB_LOGF(log,
7449dba64beSDimitry Andric                   "error: failed to get packet sequence mutex, not sending "
7450b57cec5SDimitry Andric                   "write all registers:\n%s",
7460b57cec5SDimitry Andric                   strm.GetData());
7470b57cec5SDimitry Andric       } else
7489dba64beSDimitry Andric         LLDB_LOGF(log,
7499dba64beSDimitry Andric                   "error: failed to get packet sequence mutex, not sending "
7500b57cec5SDimitry Andric                   "write all registers");
7510b57cec5SDimitry Andric     }
7520b57cec5SDimitry Andric   }
7530b57cec5SDimitry Andric   return false;
7540b57cec5SDimitry Andric }
7550b57cec5SDimitry Andric 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)7560b57cec5SDimitry Andric uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber(
7570b57cec5SDimitry Andric     lldb::RegisterKind kind, uint32_t num) {
758e8d8bef9SDimitry Andric   return m_reg_info_sp->ConvertRegisterKindToRegisterNumber(kind, num);
759e8d8bef9SDimitry Andric }
760e8d8bef9SDimitry Andric 
RegisterWriteCausesReconfigure(const llvm::StringRef name)761*5f757f3fSDimitry Andric bool GDBRemoteRegisterContext::RegisterWriteCausesReconfigure(
762*5f757f3fSDimitry Andric     const llvm::StringRef name) {
763*5f757f3fSDimitry Andric   ExecutionContext exe_ctx(CalculateThread());
764*5f757f3fSDimitry Andric   const Architecture *architecture =
765*5f757f3fSDimitry Andric       exe_ctx.GetProcessRef().GetTarget().GetArchitecturePlugin();
766*5f757f3fSDimitry Andric   return architecture && architecture->RegisterWriteCausesReconfigure(name);
767*5f757f3fSDimitry Andric }
768*5f757f3fSDimitry Andric 
ReconfigureRegisterInfo()769*5f757f3fSDimitry Andric bool GDBRemoteRegisterContext::ReconfigureRegisterInfo() {
770*5f757f3fSDimitry Andric   ExecutionContext exe_ctx(CalculateThread());
771*5f757f3fSDimitry Andric   const Architecture *architecture =
772*5f757f3fSDimitry Andric       exe_ctx.GetProcessRef().GetTarget().GetArchitecturePlugin();
773*5f757f3fSDimitry Andric   if (architecture)
774*5f757f3fSDimitry Andric     return architecture->ReconfigureRegisterInfo(*(m_reg_info_sp.get()),
775*5f757f3fSDimitry Andric                                                  m_reg_data, *this);
776e8d8bef9SDimitry Andric   return false;
7770b57cec5SDimitry Andric }
778