180814287SRaphael Isemann //===-- GDBRemoteRegisterContext.cpp --------------------------------------===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner 
930fdc8d8SChris Lattner #include "GDBRemoteRegisterContext.h"
1030fdc8d8SChris Lattner 
111ac04c30SGreg Clayton #include "lldb/Target/ExecutionContext.h"
12a332978bSJason Molenda #include "lldb/Target/Target.h"
13666cc0b2SZachary Turner #include "lldb/Utility/DataBufferHeap.h"
14666cc0b2SZachary Turner #include "lldb/Utility/DataExtractor.h"
15d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h"
16d821c997SPavel Labath #include "lldb/Utility/Scalar.h"
17bf9a7730SZachary Turner #include "lldb/Utility/StreamString.h"
1830fdc8d8SChris Lattner #include "ProcessGDBRemote.h"
19c3c0b0e5SGreg Clayton #include "ProcessGDBRemoteLog.h"
2030fdc8d8SChris Lattner #include "ThreadGDBRemote.h"
21c982c768SGreg Clayton #include "Utility/ARM_DWARF_Registers.h"
2263bd0db0SJason Molenda #include "Utility/ARM_ehframe_Registers.h"
239af71b38SPavel Labath #include "lldb/Utility/StringExtractorGDBRemote.h"
2430fdc8d8SChris Lattner 
25796ac80bSJonas Devlieghere #include <memory>
26796ac80bSJonas Devlieghere 
2730fdc8d8SChris Lattner using namespace lldb;
2830fdc8d8SChris Lattner using namespace lldb_private;
29db264a6dSTamas Berghammer using namespace lldb_private::process_gdb_remote;
3030fdc8d8SChris Lattner 
3130fdc8d8SChris Lattner // GDBRemoteRegisterContext constructor
GDBRemoteRegisterContext(ThreadGDBRemote & thread,uint32_t concrete_frame_idx,GDBRemoteDynamicRegisterInfoSP reg_info_sp,bool read_all_at_once,bool write_all_at_once)32b9c1b51eSKate Stone GDBRemoteRegisterContext::GDBRemoteRegisterContext(
33b9c1b51eSKate Stone     ThreadGDBRemote &thread, uint32_t concrete_frame_idx,
344fd77668SMuhammad Omair Javaid     GDBRemoteDynamicRegisterInfoSP reg_info_sp, bool read_all_at_once,
35b1b70f67SGuilherme Andrade     bool write_all_at_once)
364fd77668SMuhammad Omair Javaid     : RegisterContext(thread, concrete_frame_idx),
374fd77668SMuhammad Omair Javaid       m_reg_info_sp(std::move(reg_info_sp)), m_reg_valid(), m_reg_data(),
384fd77668SMuhammad Omair Javaid       m_read_all_at_once(read_all_at_once),
3953678317SMuhammad Omair Javaid       m_write_all_at_once(write_all_at_once), m_gpacket_cached(false) {
4005097246SAdrian Prantl   // Resize our vector of bools to contain one bool for every register. We will
4105097246SAdrian Prantl   // use these boolean values to know when a register value is valid in
4205097246SAdrian Prantl   // m_reg_data.
434fd77668SMuhammad Omair Javaid   m_reg_valid.resize(m_reg_info_sp->GetNumRegisters());
4430fdc8d8SChris Lattner 
4530fdc8d8SChris Lattner   // Make a heap based buffer that is big enough to store all registers
46b9c1b51eSKate Stone   DataBufferSP reg_data_sp(
474fd77668SMuhammad Omair Javaid       new DataBufferHeap(m_reg_info_sp->GetRegisterDataByteSize(), 0));
4830fdc8d8SChris Lattner   m_reg_data.SetData(reg_data_sp);
49c74c4976SGreg Clayton   m_reg_data.SetByteOrder(thread.GetProcess()->GetByteOrder());
5030fdc8d8SChris Lattner }
5130fdc8d8SChris Lattner 
5230fdc8d8SChris Lattner // Destructor
53fd2433e1SJonas Devlieghere GDBRemoteRegisterContext::~GDBRemoteRegisterContext() = default;
5430fdc8d8SChris Lattner 
InvalidateAllRegisters()55b9c1b51eSKate Stone void GDBRemoteRegisterContext::InvalidateAllRegisters() {
5630fdc8d8SChris Lattner   SetAllRegisterValid(false);
5730fdc8d8SChris Lattner }
5830fdc8d8SChris Lattner 
SetAllRegisterValid(bool b)59b9c1b51eSKate Stone void GDBRemoteRegisterContext::SetAllRegisterValid(bool b) {
6053678317SMuhammad Omair Javaid   m_gpacket_cached = b;
6130fdc8d8SChris Lattner   std::vector<bool>::iterator pos, end = m_reg_valid.end();
6230fdc8d8SChris Lattner   for (pos = m_reg_valid.begin(); pos != end; ++pos)
6330fdc8d8SChris Lattner     *pos = b;
6430fdc8d8SChris Lattner }
6530fdc8d8SChris Lattner 
GetRegisterCount()66b9c1b51eSKate Stone size_t GDBRemoteRegisterContext::GetRegisterCount() {
674fd77668SMuhammad Omair Javaid   return m_reg_info_sp->GetNumRegisters();
6830fdc8d8SChris Lattner }
6930fdc8d8SChris Lattner 
70e0d378b3SGreg Clayton const RegisterInfo *
GetRegisterInfoAtIndex(size_t reg)71b9c1b51eSKate Stone GDBRemoteRegisterContext::GetRegisterInfoAtIndex(size_t reg) {
72202af507SPavel Labath   return m_reg_info_sp->GetRegisterInfoAtIndex(reg);
7330fdc8d8SChris Lattner }
7430fdc8d8SChris Lattner 
GetRegisterSetCount()75b9c1b51eSKate Stone size_t GDBRemoteRegisterContext::GetRegisterSetCount() {
764fd77668SMuhammad Omair Javaid   return m_reg_info_sp->GetNumRegisterSets();
7730fdc8d8SChris Lattner }
7830fdc8d8SChris Lattner 
GetRegisterSet(size_t reg_set)79b9c1b51eSKate Stone const RegisterSet *GDBRemoteRegisterContext::GetRegisterSet(size_t reg_set) {
804fd77668SMuhammad Omair Javaid   return m_reg_info_sp->GetRegisterSet(reg_set);
8130fdc8d8SChris Lattner }
8230fdc8d8SChris Lattner 
ReadRegister(const RegisterInfo * reg_info,RegisterValue & value)83b9c1b51eSKate Stone bool GDBRemoteRegisterContext::ReadRegister(const RegisterInfo *reg_info,
84b9c1b51eSKate Stone                                             RegisterValue &value) {
8530fdc8d8SChris Lattner   // Read the register
8692904cc6SMichał Górny   if (ReadRegisterBytes(reg_info)) {
87f24ed3a0SJason Molenda     const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
88f24ed3a0SJason Molenda     if (m_reg_valid[reg] == false)
89f24ed3a0SJason Molenda       return false;
90f290efc3SMichał Górny     if (reg_info->value_regs &&
91f290efc3SMichał Górny         reg_info->value_regs[0] != LLDB_INVALID_REGNUM &&
92f290efc3SMichał Górny         reg_info->value_regs[1] != LLDB_INVALID_REGNUM) {
93f290efc3SMichał Górny       std::vector<char> combined_data;
94f290efc3SMichał Górny       uint32_t offset = 0;
95f290efc3SMichał Górny       for (int i = 0; reg_info->value_regs[i] != LLDB_INVALID_REGNUM; i++) {
96f290efc3SMichał Górny         const RegisterInfo *parent_reg = GetRegisterInfo(
97f290efc3SMichał Górny             eRegisterKindLLDB, reg_info->value_regs[i]);
98f290efc3SMichał Górny         if (!parent_reg)
99f290efc3SMichał Górny           return false;
100f290efc3SMichał Górny         combined_data.resize(offset + parent_reg->byte_size);
101f290efc3SMichał Górny         if (m_reg_data.CopyData(parent_reg->byte_offset, parent_reg->byte_size,
102f290efc3SMichał Górny                                 combined_data.data() + offset) !=
103f290efc3SMichał Górny             parent_reg->byte_size)
104f290efc3SMichał Górny           return false;
105f290efc3SMichał Górny         offset += parent_reg->byte_size;
106f290efc3SMichał Górny       }
107f290efc3SMichał Górny 
108f290efc3SMichał Górny       Status error;
109f290efc3SMichał Górny       return value.SetFromMemoryData(
110f290efc3SMichał Górny                  reg_info, combined_data.data(), combined_data.size(),
111f290efc3SMichał Górny                  m_reg_data.GetByteOrder(), error) == combined_data.size();
112f290efc3SMichał Górny     } else {
1137349bd90SGreg Clayton       const bool partial_data_ok = false;
11497206d57SZachary Turner       Status error(value.SetValueFromData(
11597206d57SZachary Turner           reg_info, m_reg_data, reg_info->byte_offset, partial_data_ok));
1167349bd90SGreg Clayton       return error.Success();
11730fdc8d8SChris Lattner     }
118f290efc3SMichał Górny   }
11930fdc8d8SChris Lattner   return false;
12030fdc8d8SChris Lattner }
12130fdc8d8SChris Lattner 
PrivateSetRegisterValue(uint32_t reg,llvm::ArrayRef<uint8_t> data)122b9c1b51eSKate Stone bool GDBRemoteRegisterContext::PrivateSetRegisterValue(
123b9c1b51eSKate Stone     uint32_t reg, llvm::ArrayRef<uint8_t> data) {
1243e06bd90SGreg Clayton   const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
125248a1305SKonrad Kleine   if (reg_info == nullptr)
126e576ab29SGreg Clayton     return false;
1273e06bd90SGreg Clayton 
1283e06bd90SGreg Clayton   // Invalidate if needed
1293e06bd90SGreg Clayton   InvalidateIfNeeded(false);
1303e06bd90SGreg Clayton 
131b42b48e0SPavel Labath   const size_t reg_byte_size = reg_info->byte_size;
132b9c1b51eSKate Stone   memcpy(const_cast<uint8_t *>(
133b9c1b51eSKate Stone              m_reg_data.PeekData(reg_info->byte_offset, reg_byte_size)),
134b9c1b51eSKate Stone          data.data(), std::min(data.size(), reg_byte_size));
135b42b48e0SPavel Labath   bool success = data.size() >= reg_byte_size;
136b9c1b51eSKate Stone   if (success) {
137ce1ffcf8SGreg Clayton     SetRegisterIsValid(reg, true);
138b9c1b51eSKate Stone   } else if (data.size() > 0) {
13905097246SAdrian Prantl     // Only set register is valid to false if we copied some bytes, else leave
14005097246SAdrian Prantl     // it as it was.
141ce1ffcf8SGreg Clayton     SetRegisterIsValid(reg, false);
1423e06bd90SGreg Clayton   }
143e576ab29SGreg Clayton   return success;
1443e06bd90SGreg Clayton }
1453e06bd90SGreg Clayton 
PrivateSetRegisterValue(uint32_t reg,uint64_t new_reg_val)146b9c1b51eSKate Stone bool GDBRemoteRegisterContext::PrivateSetRegisterValue(uint32_t reg,
147b9c1b51eSKate Stone                                                        uint64_t new_reg_val) {
148545304d3SJason Molenda   const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
149248a1305SKonrad Kleine   if (reg_info == nullptr)
150545304d3SJason Molenda     return false;
151545304d3SJason Molenda 
152b9c1b51eSKate Stone   // Early in process startup, we can get a thread that has an invalid byte
15305097246SAdrian Prantl   // order because the process hasn't been completely set up yet (see the ctor
15405097246SAdrian Prantl   // where the byte order is setfrom the process).  If that's the case, we
15505097246SAdrian Prantl   // can't set the value here.
156b9c1b51eSKate Stone   if (m_reg_data.GetByteOrder() == eByteOrderInvalid) {
157545304d3SJason Molenda     return false;
158545304d3SJason Molenda   }
159545304d3SJason Molenda 
160545304d3SJason Molenda   // Invalidate if needed
161545304d3SJason Molenda   InvalidateIfNeeded(false);
162545304d3SJason Molenda 
163545304d3SJason Molenda   DataBufferSP buffer_sp(new DataBufferHeap(&new_reg_val, sizeof(new_reg_val)));
164545304d3SJason Molenda   DataExtractor data(buffer_sp, endian::InlHostByteOrder(), sizeof(void *));
165545304d3SJason Molenda 
166b9c1b51eSKate Stone   // If our register context and our register info disagree, which should never
16705097246SAdrian Prantl   // happen, don't overwrite past the end of the buffer.
168545304d3SJason Molenda   if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
169545304d3SJason Molenda     return false;
170545304d3SJason Molenda 
171545304d3SJason Molenda   // Grab a pointer to where we are going to put this register
172b9c1b51eSKate Stone   uint8_t *dst = const_cast<uint8_t *>(
173b9c1b51eSKate Stone       m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
174545304d3SJason Molenda 
175248a1305SKonrad Kleine   if (dst == nullptr)
176545304d3SJason Molenda     return false;
177545304d3SJason Molenda 
178545304d3SJason Molenda   if (data.CopyByteOrderedData(0,                          // src offset
179545304d3SJason Molenda                                reg_info->byte_size,        // src length
180545304d3SJason Molenda                                dst,                        // dst
181545304d3SJason Molenda                                reg_info->byte_size,        // dst length
182545304d3SJason Molenda                                m_reg_data.GetByteOrder())) // dst byte order
183545304d3SJason Molenda   {
184545304d3SJason Molenda     SetRegisterIsValid(reg, true);
185545304d3SJason Molenda     return true;
186545304d3SJason Molenda   }
187545304d3SJason Molenda   return false;
188545304d3SJason Molenda }
189545304d3SJason Molenda 
190213ba7c7SJohnny Chen // Helper function for GDBRemoteRegisterContext::ReadRegisterBytes().
GetPrimordialRegister(const RegisterInfo * reg_info,GDBRemoteCommunicationClient & gdb_comm)191b9c1b51eSKate Stone bool GDBRemoteRegisterContext::GetPrimordialRegister(
192b9c1b51eSKate Stone     const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) {
19339f1189aSFrancis Ricci   const uint32_t lldb_reg = reg_info->kinds[eRegisterKindLLDB];
19439f1189aSFrancis Ricci   const uint32_t remote_reg = reg_info->kinds[eRegisterKindProcessPlugin];
1956be1e3daSTatyana Krasnukha 
196b9c1b51eSKate Stone   if (DataBufferSP buffer_sp =
197b9c1b51eSKate Stone           gdb_comm.ReadRegister(m_thread.GetProtocolID(), remote_reg))
198b9c1b51eSKate Stone     return PrivateSetRegisterValue(
199b9c1b51eSKate Stone         lldb_reg, llvm::ArrayRef<uint8_t>(buffer_sp->GetBytes(),
200b9c1b51eSKate Stone                                           buffer_sp->GetByteSize()));
201213ba7c7SJohnny Chen   return false;
202213ba7c7SJohnny Chen }
203f74cf86bSGreg Clayton 
ReadRegisterBytes(const RegisterInfo * reg_info)20492904cc6SMichał Górny bool GDBRemoteRegisterContext::ReadRegisterBytes(const RegisterInfo *reg_info) {
2055c95ee4dSPavel Labath   ExecutionContext exe_ctx(CalculateThread());
2065c95ee4dSPavel Labath 
2075c95ee4dSPavel Labath   Process *process = exe_ctx.GetProcessPtr();
2085c95ee4dSPavel Labath   Thread *thread = exe_ctx.GetThreadPtr();
209248a1305SKonrad Kleine   if (process == nullptr || thread == nullptr)
2105c95ee4dSPavel Labath     return false;
2115c95ee4dSPavel Labath 
212b9c1b51eSKate Stone   GDBRemoteCommunicationClient &gdb_comm(
213b9c1b51eSKate Stone       ((ProcessGDBRemote *)process)->GetGDBRemote());
2145c95ee4dSPavel Labath 
2153e06bd90SGreg Clayton   InvalidateIfNeeded(false);
2163e06bd90SGreg Clayton 
2177349bd90SGreg Clayton   const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
2187349bd90SGreg Clayton 
219b9c1b51eSKate Stone   if (!GetRegisterIsValid(reg)) {
22053678317SMuhammad Omair Javaid     if (m_read_all_at_once && !m_gpacket_cached) {
221b9c1b51eSKate Stone       if (DataBufferSP buffer_sp =
222b9c1b51eSKate Stone               gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) {
223b9c1b51eSKate Stone         memcpy(const_cast<uint8_t *>(m_reg_data.GetDataStart()),
224b9c1b51eSKate Stone                buffer_sp->GetBytes(),
225b42b48e0SPavel Labath                std::min(buffer_sp->GetByteSize(), m_reg_data.GetByteSize()));
226b9c1b51eSKate Stone         if (buffer_sp->GetByteSize() >= m_reg_data.GetByteSize()) {
22730fdc8d8SChris Lattner           SetAllRegisterValid(true);
228b42b48e0SPavel Labath           return true;
229f24ed3a0SJason Molenda         } else if (buffer_sp->GetByteSize() > 0) {
230ecfab0b6SMichał Górny           for (auto x : llvm::enumerate(m_reg_info_sp->registers())) {
231ecfab0b6SMichał Górny             const struct RegisterInfo &reginfo = x.value();
232ecfab0b6SMichał Górny             m_reg_valid[x.index()] =
233ecfab0b6SMichał Górny                 (reginfo.byte_offset + reginfo.byte_size <=
234ecfab0b6SMichał Górny                  buffer_sp->GetByteSize());
235f24ed3a0SJason Molenda           }
23653678317SMuhammad Omair Javaid 
23753678317SMuhammad Omair Javaid           m_gpacket_cached = true;
23853678317SMuhammad Omair Javaid           if (GetRegisterIsValid(reg))
239f24ed3a0SJason Molenda             return true;
2408130bf67SJason Molenda         } else {
241b1127753SPavel Labath           Log *log(GetLog(GDBRLog::Thread | GDBRLog::Packets));
24263e5fb76SJonas Devlieghere           LLDB_LOGF(
24363e5fb76SJonas Devlieghere               log,
24463e5fb76SJonas Devlieghere               "error: GDBRemoteRegisterContext::ReadRegisterBytes tried "
24563e5fb76SJonas Devlieghere               "to read the "
24663e5fb76SJonas Devlieghere               "entire register context at once, expected at least %" PRId64
24763e5fb76SJonas Devlieghere               " bytes "
24863e5fb76SJonas Devlieghere               "but only got %" PRId64 " bytes.",
24963e5fb76SJonas Devlieghere               m_reg_data.GetByteSize(), buffer_sp->GetByteSize());
250b42b48e0SPavel Labath           return false;
251b42b48e0SPavel Labath         }
25253678317SMuhammad Omair Javaid       }
25353678317SMuhammad Omair Javaid     }
254b9c1b51eSKate Stone     if (reg_info->value_regs) {
255b9c1b51eSKate Stone       // Process this composite register request by delegating to the
25605097246SAdrian Prantl       // constituent primordial registers.
257213ba7c7SJohnny Chen 
258213ba7c7SJohnny Chen       // Index of the primordial register.
259213ba7c7SJohnny Chen       bool success = true;
260b9c1b51eSKate Stone       for (uint32_t idx = 0; success; ++idx) {
261ce1ffcf8SGreg Clayton         const uint32_t prim_reg = reg_info->value_regs[idx];
262ce1ffcf8SGreg Clayton         if (prim_reg == LLDB_INVALID_REGNUM)
263ce1ffcf8SGreg Clayton           break;
26405097246SAdrian Prantl         // We have a valid primordial register as our constituent. Grab the
26505097246SAdrian Prantl         // corresponding register info.
2668561ad92SMuhammad Omair Javaid         const RegisterInfo *prim_reg_info =
267cc3c788aSMichał Górny             GetRegisterInfo(eRegisterKindLLDB, prim_reg);
268248a1305SKonrad Kleine         if (prim_reg_info == nullptr)
269213ba7c7SJohnny Chen           success = false;
270b9c1b51eSKate Stone         else {
271ce1ffcf8SGreg Clayton           // Read the containing register if it hasn't already been read
272ce1ffcf8SGreg Clayton           if (!GetRegisterIsValid(prim_reg))
2735c95ee4dSPavel Labath             success = GetPrimordialRegister(prim_reg_info, gdb_comm);
274213ba7c7SJohnny Chen         }
275213ba7c7SJohnny Chen       }
276ce1ffcf8SGreg Clayton 
277b9c1b51eSKate Stone       if (success) {
278b9c1b51eSKate Stone         // If we reach this point, all primordial register requests have
27905097246SAdrian Prantl         // succeeded. Validate this composite register.
280ce1ffcf8SGreg Clayton         SetRegisterIsValid(reg_info, true);
281213ba7c7SJohnny Chen       }
282b9c1b51eSKate Stone     } else {
283ce1ffcf8SGreg Clayton       // Get each register individually
2845c95ee4dSPavel Labath       GetPrimordialRegister(reg_info, gdb_comm);
285ce1ffcf8SGreg Clayton     }
28630fdc8d8SChris Lattner 
2873e06bd90SGreg Clayton     // Make sure we got a valid register value after reading it
288ce1ffcf8SGreg Clayton     if (!GetRegisterIsValid(reg))
2893e06bd90SGreg Clayton       return false;
2903e06bd90SGreg Clayton   }
2913e06bd90SGreg Clayton 
2923e06bd90SGreg Clayton   return true;
29330fdc8d8SChris Lattner }
29430fdc8d8SChris Lattner 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & value)295b9c1b51eSKate Stone bool GDBRemoteRegisterContext::WriteRegister(const RegisterInfo *reg_info,
296b9c1b51eSKate Stone                                              const RegisterValue &value) {
29730fdc8d8SChris Lattner   DataExtractor data;
298f290efc3SMichał Górny   if (value.GetData(data)) {
299f290efc3SMichał Górny     if (reg_info->value_regs &&
300f290efc3SMichał Górny         reg_info->value_regs[0] != LLDB_INVALID_REGNUM &&
301f290efc3SMichał Górny         reg_info->value_regs[1] != LLDB_INVALID_REGNUM) {
302f290efc3SMichał Górny       uint32_t combined_size = 0;
303f290efc3SMichał Górny       for (int i = 0; reg_info->value_regs[i] != LLDB_INVALID_REGNUM; i++) {
304f290efc3SMichał Górny         const RegisterInfo *parent_reg = GetRegisterInfo(
305f290efc3SMichał Górny             eRegisterKindLLDB, reg_info->value_regs[i]);
306f290efc3SMichał Górny         if (!parent_reg)
307f290efc3SMichał Górny           return false;
308f290efc3SMichał Górny         combined_size += parent_reg->byte_size;
309f290efc3SMichał Górny       }
310f290efc3SMichał Górny 
311f290efc3SMichał Górny       if (data.GetByteSize() < combined_size)
312f290efc3SMichał Górny         return false;
313f290efc3SMichał Górny 
314f290efc3SMichał Górny       uint32_t offset = 0;
315f290efc3SMichał Górny       for (int i = 0; reg_info->value_regs[i] != LLDB_INVALID_REGNUM; i++) {
316f290efc3SMichał Górny         const RegisterInfo *parent_reg = GetRegisterInfo(
317f290efc3SMichał Górny             eRegisterKindLLDB, reg_info->value_regs[i]);
318f290efc3SMichał Górny         assert(parent_reg);
319f290efc3SMichał Górny 
320f290efc3SMichał Górny         DataExtractor parent_data{data, offset, parent_reg->byte_size};
321f290efc3SMichał Górny         if (!WriteRegisterBytes(parent_reg, parent_data, 0))
322f290efc3SMichał Górny           return false;
323f290efc3SMichał Górny         offset += parent_reg->byte_size;
324f290efc3SMichał Górny       }
325f290efc3SMichał Górny       assert(offset == combined_size);
326f290efc3SMichał Górny       return true;
327f290efc3SMichał Górny     } else
32893ecc368SGreg Clayton       return WriteRegisterBytes(reg_info, data, 0);
329f290efc3SMichał Górny   }
33030fdc8d8SChris Lattner   return false;
33130fdc8d8SChris Lattner }
33230fdc8d8SChris Lattner 
333213ba7c7SJohnny Chen // Helper function for GDBRemoteRegisterContext::WriteRegisterBytes().
SetPrimordialRegister(const RegisterInfo * reg_info,GDBRemoteCommunicationClient & gdb_comm)334b9c1b51eSKate Stone bool GDBRemoteRegisterContext::SetPrimordialRegister(
335b9c1b51eSKate Stone     const RegisterInfo *reg_info, GDBRemoteCommunicationClient &gdb_comm) {
336213ba7c7SJohnny Chen   StreamString packet;
337213ba7c7SJohnny Chen   StringExtractorGDBRemote response;
338213ba7c7SJohnny Chen   const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
339213ba7c7SJohnny Chen   // Invalidate just this register
340ce1ffcf8SGreg Clayton   SetRegisterIsValid(reg, false);
341d43ae376SPavel Labath 
342d43ae376SPavel Labath   return gdb_comm.WriteRegister(
343d43ae376SPavel Labath       m_thread.GetProtocolID(), reg_info->kinds[eRegisterKindProcessPlugin],
344b9c1b51eSKate Stone       {m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size),
345b9c1b51eSKate Stone        reg_info->byte_size});
346213ba7c7SJohnny Chen }
347279ceecfSJim Ingham 
WriteRegisterBytes(const RegisterInfo * reg_info,DataExtractor & data,uint32_t data_offset)348b9c1b51eSKate Stone bool GDBRemoteRegisterContext::WriteRegisterBytes(const RegisterInfo *reg_info,
349b9c1b51eSKate Stone                                                   DataExtractor &data,
350b9c1b51eSKate Stone                                                   uint32_t data_offset) {
3511ac04c30SGreg Clayton   ExecutionContext exe_ctx(CalculateThread());
3521ac04c30SGreg Clayton 
3531ac04c30SGreg Clayton   Process *process = exe_ctx.GetProcessPtr();
3541ac04c30SGreg Clayton   Thread *thread = exe_ctx.GetThreadPtr();
355248a1305SKonrad Kleine   if (process == nullptr || thread == nullptr)
3561ac04c30SGreg Clayton     return false;
3571ac04c30SGreg Clayton 
358b9c1b51eSKate Stone   GDBRemoteCommunicationClient &gdb_comm(
359b9c1b51eSKate Stone       ((ProcessGDBRemote *)process)->GetGDBRemote());
3609e7da0fbSJason Molenda 
361b9c1b51eSKate Stone   assert(m_reg_data.GetByteSize() >=
362b9c1b51eSKate Stone          reg_info->byte_offset + reg_info->byte_size);
3639e7da0fbSJason Molenda 
364b9c1b51eSKate Stone   // If our register context and our register info disagree, which should never
36505097246SAdrian Prantl   // happen, don't overwrite past the end of the buffer.
3669e7da0fbSJason Molenda   if (m_reg_data.GetByteSize() < reg_info->byte_offset + reg_info->byte_size)
3679e7da0fbSJason Molenda     return false;
3689e7da0fbSJason Molenda 
36930fdc8d8SChris Lattner   // Grab a pointer to where we are going to put this register
370b9c1b51eSKate Stone   uint8_t *dst = const_cast<uint8_t *>(
371b9c1b51eSKate Stone       m_reg_data.PeekData(reg_info->byte_offset, reg_info->byte_size));
37230fdc8d8SChris Lattner 
373248a1305SKonrad Kleine   if (dst == nullptr)
37430fdc8d8SChris Lattner     return false;
37530fdc8d8SChris Lattner 
376e448ad78SMuhammad Omair Javaid   // Code below is specific to AArch64 target in SVE state
377e448ad78SMuhammad Omair Javaid   // If vector granule (vg) register is being written then thread's
378e448ad78SMuhammad Omair Javaid   // register context reconfiguration is triggered on success.
379e448ad78SMuhammad Omair Javaid   bool do_reconfigure_arm64_sve = false;
380e448ad78SMuhammad Omair Javaid   const ArchSpec &arch = process->GetTarget().GetArchitecture();
381e448ad78SMuhammad Omair Javaid   if (arch.IsValid() && arch.GetTriple().isAArch64())
382e448ad78SMuhammad Omair Javaid     if (strcmp(reg_info->name, "vg") == 0)
383e448ad78SMuhammad Omair Javaid       do_reconfigure_arm64_sve = true;
384e448ad78SMuhammad Omair Javaid 
3857349bd90SGreg Clayton   if (data.CopyByteOrderedData(data_offset,                // src offset
3867349bd90SGreg Clayton                                reg_info->byte_size,        // src length
3877349bd90SGreg Clayton                                dst,                        // dst
3887349bd90SGreg Clayton                                reg_info->byte_size,        // dst length
3897349bd90SGreg Clayton                                m_reg_data.GetByteOrder())) // dst byte order
39030fdc8d8SChris Lattner   {
391379f24ffSJim Ingham     GDBRemoteClientBase::Lock lock(gdb_comm);
392b9c1b51eSKate Stone     if (lock) {
393b1b70f67SGuilherme Andrade       if (m_write_all_at_once) {
39430fdc8d8SChris Lattner         // Invalidate all register values
3953e06bd90SGreg Clayton         InvalidateIfNeeded(true);
39630fdc8d8SChris Lattner 
397b42b48e0SPavel Labath         // Set all registers in one packet
398b9c1b51eSKate Stone         if (gdb_comm.WriteAllRegisters(
399b9c1b51eSKate Stone                 m_thread.GetProtocolID(),
4005c95ee4dSPavel Labath                 {m_reg_data.GetDataStart(), size_t(m_reg_data.GetByteSize())}))
401b42b48e0SPavel Labath 
40230fdc8d8SChris Lattner         {
40330fdc8d8SChris Lattner           SetAllRegisterValid(false);
404e448ad78SMuhammad Omair Javaid 
405e448ad78SMuhammad Omair Javaid           if (do_reconfigure_arm64_sve)
406e448ad78SMuhammad Omair Javaid             AArch64SVEReconfigure();
407e448ad78SMuhammad Omair Javaid 
40830fdc8d8SChris Lattner           return true;
40930fdc8d8SChris Lattner         }
410b9c1b51eSKate Stone       } else {
411ce1ffcf8SGreg Clayton         bool success = true;
412ce1ffcf8SGreg Clayton 
413b9c1b51eSKate Stone         if (reg_info->value_regs) {
41405097246SAdrian Prantl           // This register is part of another register. In this case we read
41505097246SAdrian Prantl           // the actual register data for any "value_regs", and once all that
41605097246SAdrian Prantl           // data is read, we will have enough data in our register context
41705097246SAdrian Prantl           // bytes for the value of this register
418ce1ffcf8SGreg Clayton 
419ce1ffcf8SGreg Clayton           // Invalidate this composite register first.
420ce1ffcf8SGreg Clayton 
421b9c1b51eSKate Stone           for (uint32_t idx = 0; success; ++idx) {
422ce1ffcf8SGreg Clayton             const uint32_t reg = reg_info->value_regs[idx];
423ce1ffcf8SGreg Clayton             if (reg == LLDB_INVALID_REGNUM)
424ce1ffcf8SGreg Clayton               break;
42505097246SAdrian Prantl             // We have a valid primordial register as our constituent. Grab the
42605097246SAdrian Prantl             // corresponding register info.
4278561ad92SMuhammad Omair Javaid             const RegisterInfo *value_reg_info =
428cc3c788aSMichał Górny                 GetRegisterInfo(eRegisterKindLLDB, reg);
429248a1305SKonrad Kleine             if (value_reg_info == nullptr)
430ce1ffcf8SGreg Clayton               success = false;
431ce1ffcf8SGreg Clayton             else
4325c95ee4dSPavel Labath               success = SetPrimordialRegister(value_reg_info, gdb_comm);
433ce1ffcf8SGreg Clayton           }
434b9c1b51eSKate Stone         } else {
435ce1ffcf8SGreg Clayton           // This is an actual register, write it
4365c95ee4dSPavel Labath           success = SetPrimordialRegister(reg_info, gdb_comm);
437e448ad78SMuhammad Omair Javaid 
438e448ad78SMuhammad Omair Javaid           if (success && do_reconfigure_arm64_sve)
439e448ad78SMuhammad Omair Javaid             AArch64SVEReconfigure();
440ce1ffcf8SGreg Clayton         }
44130fdc8d8SChris Lattner 
442b9c1b51eSKate Stone         // Check if writing this register will invalidate any other register
44305097246SAdrian Prantl         // values? If so, invalidate them
444b9c1b51eSKate Stone         if (reg_info->invalidate_regs) {
445ce1ffcf8SGreg Clayton           for (uint32_t idx = 0, reg = reg_info->invalidate_regs[0];
446ce1ffcf8SGreg Clayton                reg != LLDB_INVALID_REGNUM;
4478561ad92SMuhammad Omair Javaid                reg = reg_info->invalidate_regs[++idx])
4488561ad92SMuhammad Omair Javaid             SetRegisterIsValid(ConvertRegisterKindToRegisterNumber(
449cc3c788aSMichał Górny                                    eRegisterKindLLDB, reg),
4508561ad92SMuhammad Omair Javaid                                false);
45130fdc8d8SChris Lattner         }
452213ba7c7SJohnny Chen 
453213ba7c7SJohnny Chen         return success;
45430fdc8d8SChris Lattner       }
455b9c1b51eSKate Stone     } else {
456b1127753SPavel Labath       Log *log(GetLog(GDBRLog::Thread | GDBRLog::Packets));
457b9c1b51eSKate Stone       if (log) {
458b9c1b51eSKate Stone         if (log->GetVerbose()) {
459d451c1a8SGreg Clayton           StreamString strm;
460d451c1a8SGreg Clayton           gdb_comm.DumpHistory(strm);
46163e5fb76SJonas Devlieghere           LLDB_LOGF(log,
46263e5fb76SJonas Devlieghere                     "error: failed to get packet sequence mutex, not sending "
463b9c1b51eSKate Stone                     "write register for \"%s\":\n%s",
464b9c1b51eSKate Stone                     reg_info->name, strm.GetData());
465b9c1b51eSKate Stone         } else
46663e5fb76SJonas Devlieghere           LLDB_LOGF(log,
46763e5fb76SJonas Devlieghere                     "error: failed to get packet sequence mutex, not sending "
468b9c1b51eSKate Stone                     "write register for \"%s\"",
469b9c1b51eSKate Stone                     reg_info->name);
470c3c0b0e5SGreg Clayton       }
47130fdc8d8SChris Lattner     }
472d451c1a8SGreg Clayton   }
47330fdc8d8SChris Lattner   return false;
47430fdc8d8SChris Lattner }
47530fdc8d8SChris Lattner 
ReadAllRegisterValues(RegisterCheckpoint & reg_checkpoint)476b9c1b51eSKate Stone bool GDBRemoteRegisterContext::ReadAllRegisterValues(
477b9c1b51eSKate Stone     RegisterCheckpoint &reg_checkpoint) {
478f74cf86bSGreg Clayton   ExecutionContext exe_ctx(CalculateThread());
479f74cf86bSGreg Clayton 
480f74cf86bSGreg Clayton   Process *process = exe_ctx.GetProcessPtr();
481f74cf86bSGreg Clayton   Thread *thread = exe_ctx.GetThreadPtr();
482248a1305SKonrad Kleine   if (process == nullptr || thread == nullptr)
483f74cf86bSGreg Clayton     return false;
484f74cf86bSGreg Clayton 
485b9c1b51eSKate Stone   GDBRemoteCommunicationClient &gdb_comm(
486b9c1b51eSKate Stone       ((ProcessGDBRemote *)process)->GetGDBRemote());
487f74cf86bSGreg Clayton 
488f74cf86bSGreg Clayton   uint32_t save_id = 0;
489b9c1b51eSKate Stone   if (gdb_comm.SaveRegisterState(thread->GetProtocolID(), save_id)) {
490f74cf86bSGreg Clayton     reg_checkpoint.SetID(save_id);
491f74cf86bSGreg Clayton     reg_checkpoint.GetData().reset();
492f74cf86bSGreg Clayton     return true;
493b9c1b51eSKate Stone   } else {
494f74cf86bSGreg Clayton     reg_checkpoint.SetID(0); // Invalid save ID is zero
495f74cf86bSGreg Clayton     return ReadAllRegisterValues(reg_checkpoint.GetData());
496f74cf86bSGreg Clayton   }
497f74cf86bSGreg Clayton }
498f74cf86bSGreg Clayton 
WriteAllRegisterValues(const RegisterCheckpoint & reg_checkpoint)499b9c1b51eSKate Stone bool GDBRemoteRegisterContext::WriteAllRegisterValues(
500b9c1b51eSKate Stone     const RegisterCheckpoint &reg_checkpoint) {
501f74cf86bSGreg Clayton   uint32_t save_id = reg_checkpoint.GetID();
502b9c1b51eSKate Stone   if (save_id != 0) {
503f74cf86bSGreg Clayton     ExecutionContext exe_ctx(CalculateThread());
504f74cf86bSGreg Clayton 
505f74cf86bSGreg Clayton     Process *process = exe_ctx.GetProcessPtr();
506f74cf86bSGreg Clayton     Thread *thread = exe_ctx.GetThreadPtr();
507248a1305SKonrad Kleine     if (process == nullptr || thread == nullptr)
508f74cf86bSGreg Clayton       return false;
509f74cf86bSGreg Clayton 
510b9c1b51eSKate Stone     GDBRemoteCommunicationClient &gdb_comm(
511b9c1b51eSKate Stone         ((ProcessGDBRemote *)process)->GetGDBRemote());
512f74cf86bSGreg Clayton 
513f74cf86bSGreg Clayton     return gdb_comm.RestoreRegisterState(m_thread.GetProtocolID(), save_id);
514b9c1b51eSKate Stone   } else {
515f74cf86bSGreg Clayton     return WriteAllRegisterValues(reg_checkpoint.GetData());
516f74cf86bSGreg Clayton   }
517f74cf86bSGreg Clayton }
51830fdc8d8SChris Lattner 
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)519b9c1b51eSKate Stone bool GDBRemoteRegisterContext::ReadAllRegisterValues(
520*fc54427eSJonas Devlieghere     lldb::WritableDataBufferSP &data_sp) {
5211ac04c30SGreg Clayton   ExecutionContext exe_ctx(CalculateThread());
5221ac04c30SGreg Clayton 
5231ac04c30SGreg Clayton   Process *process = exe_ctx.GetProcessPtr();
5241ac04c30SGreg Clayton   Thread *thread = exe_ctx.GetThreadPtr();
525248a1305SKonrad Kleine   if (process == nullptr || thread == nullptr)
5261ac04c30SGreg Clayton     return false;
5271ac04c30SGreg Clayton 
528b9c1b51eSKate Stone   GDBRemoteCommunicationClient &gdb_comm(
529b9c1b51eSKate Stone       ((ProcessGDBRemote *)process)->GetGDBRemote());
5301ac04c30SGreg Clayton 
531b9c1b51eSKate Stone   const bool use_g_packet =
532a6682a41SJonas Devlieghere       !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);
533a332978bSJason Molenda 
534379f24ffSJim Ingham   GDBRemoteClientBase::Lock lock(gdb_comm);
535b9c1b51eSKate Stone   if (lock) {
53627402d2aSPavel Labath     if (gdb_comm.SyncThreadState(m_thread.GetProtocolID()))
53727402d2aSPavel Labath       InvalidateAllRegisters();
538279ceecfSJim Ingham 
539*fc54427eSJonas Devlieghere     if (use_g_packet) {
540*fc54427eSJonas Devlieghere       if (DataBufferSP data_buffer =
541*fc54427eSJonas Devlieghere               gdb_comm.ReadAllRegisters(m_thread.GetProtocolID())) {
542*fc54427eSJonas Devlieghere         data_sp = std::make_shared<DataBufferHeap>(*data_buffer);
54330fdc8d8SChris Lattner         return true;
544*fc54427eSJonas Devlieghere       }
545*fc54427eSJonas Devlieghere     }
546a332978bSJason Molenda 
547b42b48e0SPavel Labath     // We're going to read each register
548b42b48e0SPavel Labath     // individually and store them as binary data in a buffer.
549b42b48e0SPavel Labath     const RegisterInfo *reg_info;
550a332978bSJason Molenda 
551248a1305SKonrad Kleine     for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != nullptr;
552248a1305SKonrad Kleine          i++) {
553b9c1b51eSKate Stone       if (reg_info
554b9c1b51eSKate Stone               ->value_regs) // skip registers that are slices of real registers
555a332978bSJason Molenda         continue;
55692904cc6SMichał Górny       ReadRegisterBytes(reg_info);
557b9c1b51eSKate Stone       // ReadRegisterBytes saves the contents of the register in to the
558b9c1b51eSKate Stone       // m_reg_data buffer
559a332978bSJason Molenda     }
560796ac80bSJonas Devlieghere     data_sp = std::make_shared<DataBufferHeap>(
5614fd77668SMuhammad Omair Javaid         m_reg_data.GetDataStart(), m_reg_info_sp->GetRegisterDataByteSize());
562a332978bSJason Molenda     return true;
563b9c1b51eSKate Stone   } else {
564a332978bSJason Molenda 
565b1127753SPavel Labath     Log *log(GetLog(GDBRLog::Thread | GDBRLog::Packets));
566b9c1b51eSKate Stone     if (log) {
567b9c1b51eSKate Stone       if (log->GetVerbose()) {
568d451c1a8SGreg Clayton         StreamString strm;
569d451c1a8SGreg Clayton         gdb_comm.DumpHistory(strm);
57063e5fb76SJonas Devlieghere         LLDB_LOGF(log,
57163e5fb76SJonas Devlieghere                   "error: failed to get packet sequence mutex, not sending "
572b9c1b51eSKate Stone                   "read all registers:\n%s",
573b9c1b51eSKate Stone                   strm.GetData());
574b9c1b51eSKate Stone       } else
57563e5fb76SJonas Devlieghere         LLDB_LOGF(log,
57663e5fb76SJonas Devlieghere                   "error: failed to get packet sequence mutex, not sending "
577b9c1b51eSKate Stone                   "read all registers");
578c3c0b0e5SGreg Clayton     }
579d451c1a8SGreg Clayton   }
580c3c0b0e5SGreg Clayton 
581e6a9e439SGreg Clayton   data_sp.reset();
58230fdc8d8SChris Lattner   return false;
58330fdc8d8SChris Lattner }
58430fdc8d8SChris Lattner 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)585b9c1b51eSKate Stone bool GDBRemoteRegisterContext::WriteAllRegisterValues(
586b9c1b51eSKate Stone     const lldb::DataBufferSP &data_sp) {
587248a1305SKonrad Kleine   if (!data_sp || data_sp->GetBytes() == nullptr || data_sp->GetByteSize() == 0)
58873b472d4SGreg Clayton     return false;
58973b472d4SGreg Clayton 
5901ac04c30SGreg Clayton   ExecutionContext exe_ctx(CalculateThread());
5911ac04c30SGreg Clayton 
5921ac04c30SGreg Clayton   Process *process = exe_ctx.GetProcessPtr();
5931ac04c30SGreg Clayton   Thread *thread = exe_ctx.GetThreadPtr();
594248a1305SKonrad Kleine   if (process == nullptr || thread == nullptr)
5951ac04c30SGreg Clayton     return false;
5961ac04c30SGreg Clayton 
597b9c1b51eSKate Stone   GDBRemoteCommunicationClient &gdb_comm(
598b9c1b51eSKate Stone       ((ProcessGDBRemote *)process)->GetGDBRemote());
5991ac04c30SGreg Clayton 
600b9c1b51eSKate Stone   const bool use_g_packet =
601a6682a41SJonas Devlieghere       !gdb_comm.AvoidGPackets((ProcessGDBRemote *)process);
602a332978bSJason Molenda 
603379f24ffSJim Ingham   GDBRemoteClientBase::Lock lock(gdb_comm);
604b9c1b51eSKate Stone   if (lock) {
60556d7262bSPavel Labath     // The data_sp contains the G response packet.
606b9c1b51eSKate Stone     if (use_g_packet) {
607b9c1b51eSKate Stone       if (gdb_comm.WriteAllRegisters(
608b9c1b51eSKate Stone               m_thread.GetProtocolID(),
6095c95ee4dSPavel Labath               {data_sp->GetBytes(), size_t(data_sp->GetByteSize())}))
61030fdc8d8SChris Lattner         return true;
61156d7262bSPavel Labath 
61293ecc368SGreg Clayton       uint32_t num_restored = 0;
61305097246SAdrian Prantl       // We need to manually go through all of the registers and restore them
61405097246SAdrian Prantl       // manually
615b9c1b51eSKate Stone       DataExtractor restore_data(data_sp, m_reg_data.GetByteOrder(),
616b9c1b51eSKate Stone                                  m_reg_data.GetAddressByteSize());
617e6a9e439SGreg Clayton 
61893ecc368SGreg Clayton       const RegisterInfo *reg_info;
61993ecc368SGreg Clayton 
62005097246SAdrian Prantl       // The g packet contents may either include the slice registers
62105097246SAdrian Prantl       // (registers defined in terms of other registers, e.g. eax is a subset
62205097246SAdrian Prantl       // of rax) or not.  The slice registers should NOT be in the g packet,
62305097246SAdrian Prantl       // but some implementations may incorrectly include them.
624a332978bSJason Molenda       //
625b9c1b51eSKate Stone       // If the slice registers are included in the packet, we must step over
62605097246SAdrian Prantl       // the slice registers when parsing the packet -- relying on the
62705097246SAdrian Prantl       // RegisterInfo byte_offset field would be incorrect. If the slice
62805097246SAdrian Prantl       // registers are not included, then using the byte_offset values into the
629a332978bSJason Molenda       // data buffer is the best way to find individual register values.
630a332978bSJason Molenda 
631a746e8e5SZachary Turner       uint64_t size_including_slice_registers = 0;
632a746e8e5SZachary Turner       uint64_t size_not_including_slice_registers = 0;
633a746e8e5SZachary Turner       uint64_t size_by_highest_offset = 0;
634a332978bSJason Molenda 
635b9c1b51eSKate Stone       for (uint32_t reg_idx = 0;
636248a1305SKonrad Kleine            (reg_info = GetRegisterInfoAtIndex(reg_idx)) != nullptr; ++reg_idx) {
637a332978bSJason Molenda         size_including_slice_registers += reg_info->byte_size;
638248a1305SKonrad Kleine         if (reg_info->value_regs == nullptr)
639a332978bSJason Molenda           size_not_including_slice_registers += reg_info->byte_size;
640a746e8e5SZachary Turner         if (reg_info->byte_offset >= size_by_highest_offset)
641a332978bSJason Molenda           size_by_highest_offset = reg_info->byte_offset + reg_info->byte_size;
642a332978bSJason Molenda       }
643a332978bSJason Molenda 
644a332978bSJason Molenda       bool use_byte_offset_into_buffer;
645b9c1b51eSKate Stone       if (size_by_highest_offset == restore_data.GetByteSize()) {
646b9c1b51eSKate Stone         // The size of the packet agrees with the highest offset: + size in the
647b9c1b51eSKate Stone         // register file
648a332978bSJason Molenda         use_byte_offset_into_buffer = true;
649b9c1b51eSKate Stone       } else if (size_not_including_slice_registers ==
650b9c1b51eSKate Stone                  restore_data.GetByteSize()) {
651b9c1b51eSKate Stone         // The size of the packet is the same as concatenating all of the
65205097246SAdrian Prantl         // registers sequentially, skipping the slice registers
653a332978bSJason Molenda         use_byte_offset_into_buffer = true;
654b9c1b51eSKate Stone       } else if (size_including_slice_registers == restore_data.GetByteSize()) {
655b9c1b51eSKate Stone         // The slice registers are present in the packet (when they shouldn't
65605097246SAdrian Prantl         // be). Don't try to use the RegisterInfo byte_offset into the
65705097246SAdrian Prantl         // restore_data, it will point to the wrong place.
658a332978bSJason Molenda         use_byte_offset_into_buffer = false;
659b9c1b51eSKate Stone       } else {
660b9c1b51eSKate Stone         // None of our expected sizes match the actual g packet data we're
66105097246SAdrian Prantl         // looking at. The most conservative approach here is to use the
66205097246SAdrian Prantl         // running total byte offset.
663a332978bSJason Molenda         use_byte_offset_into_buffer = false;
664a332978bSJason Molenda       }
665a332978bSJason Molenda 
666a332978bSJason Molenda       // In case our register definitions don't include the correct offsets,
667a332978bSJason Molenda       // keep track of the size of each reg & compute offset based on that.
668a332978bSJason Molenda       uint32_t running_byte_offset = 0;
669b9c1b51eSKate Stone       for (uint32_t reg_idx = 0;
670248a1305SKonrad Kleine            (reg_info = GetRegisterInfoAtIndex(reg_idx)) != nullptr;
671b9c1b51eSKate Stone            ++reg_idx, running_byte_offset += reg_info->byte_size) {
672a332978bSJason Molenda         // Skip composite aka slice registers (e.g. eax is a slice of rax).
673213ba7c7SJohnny Chen         if (reg_info->value_regs)
674213ba7c7SJohnny Chen           continue;
675213ba7c7SJohnny Chen 
676a332978bSJason Molenda         const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
677a332978bSJason Molenda 
678a332978bSJason Molenda         uint32_t register_offset;
679b9c1b51eSKate Stone         if (use_byte_offset_into_buffer) {
680a332978bSJason Molenda           register_offset = reg_info->byte_offset;
681b9c1b51eSKate Stone         } else {
682a332978bSJason Molenda           register_offset = running_byte_offset;
683a332978bSJason Molenda         }
684a332978bSJason Molenda 
68593ecc368SGreg Clayton         const uint32_t reg_byte_size = reg_info->byte_size;
686e6a9e439SGreg Clayton 
687b9c1b51eSKate Stone         const uint8_t *restore_src =
688b9c1b51eSKate Stone             restore_data.PeekData(register_offset, reg_byte_size);
689b9c1b51eSKate Stone         if (restore_src) {
690a332978bSJason Molenda           SetRegisterIsValid(reg, false);
691b9c1b51eSKate Stone           if (gdb_comm.WriteRegister(
692b9c1b51eSKate Stone                   m_thread.GetProtocolID(),
693b9c1b51eSKate Stone                   reg_info->kinds[eRegisterKindProcessPlugin],
6945c95ee4dSPavel Labath                   {restore_src, reg_byte_size}))
69593ecc368SGreg Clayton             ++num_restored;
69693ecc368SGreg Clayton         }
697e6a9e439SGreg Clayton       }
69893ecc368SGreg Clayton       return num_restored > 0;
699b9c1b51eSKate Stone     } else {
700a332978bSJason Molenda       // For the use_g_packet == false case, we're going to write each register
701a332978bSJason Molenda       // individually.  The data buffer is binary data in this case, instead of
702a332978bSJason Molenda       // ascii characters.
703a332978bSJason Molenda 
704a332978bSJason Molenda       bool arm64_debugserver = false;
705b9c1b51eSKate Stone       if (m_thread.GetProcess().get()) {
706b9c1b51eSKate Stone         const ArchSpec &arch =
707b9c1b51eSKate Stone             m_thread.GetProcess()->GetTarget().GetArchitecture();
708e448ad78SMuhammad Omair Javaid         if (arch.IsValid() && (arch.GetMachine() == llvm::Triple::aarch64 ||
7097dd7a360SJason Molenda                                arch.GetMachine() == llvm::Triple::aarch64_32) &&
71056d7262bSPavel Labath             arch.GetTriple().getVendor() == llvm::Triple::Apple &&
711b9c1b51eSKate Stone             arch.GetTriple().getOS() == llvm::Triple::IOS) {
712a332978bSJason Molenda           arm64_debugserver = true;
713a332978bSJason Molenda         }
714a332978bSJason Molenda       }
715a332978bSJason Molenda       uint32_t num_restored = 0;
716a332978bSJason Molenda       const RegisterInfo *reg_info;
717248a1305SKonrad Kleine       for (uint32_t i = 0; (reg_info = GetRegisterInfoAtIndex(i)) != nullptr;
718b9c1b51eSKate Stone            i++) {
719b9c1b51eSKate Stone         if (reg_info->value_regs) // skip registers that are slices of real
720b9c1b51eSKate Stone                                   // registers
721a332978bSJason Molenda           continue;
72205097246SAdrian Prantl         // Skip the fpsr and fpcr floating point status/control register
72305097246SAdrian Prantl         // writing to work around a bug in an older version of debugserver that
72405097246SAdrian Prantl         // would lead to register context corruption when writing fpsr/fpcr.
725b9c1b51eSKate Stone         if (arm64_debugserver && (strcmp(reg_info->name, "fpsr") == 0 ||
726b9c1b51eSKate Stone                                   strcmp(reg_info->name, "fpcr") == 0)) {
727a332978bSJason Molenda           continue;
728a332978bSJason Molenda         }
729a332978bSJason Molenda 
730a332978bSJason Molenda         SetRegisterIsValid(reg_info, false);
731b9c1b51eSKate Stone         if (gdb_comm.WriteRegister(m_thread.GetProtocolID(),
732b9c1b51eSKate Stone                                    reg_info->kinds[eRegisterKindProcessPlugin],
733b9c1b51eSKate Stone                                    {data_sp->GetBytes() + reg_info->byte_offset,
734b9c1b51eSKate Stone                                     reg_info->byte_size}))
735a332978bSJason Molenda           ++num_restored;
736a332978bSJason Molenda       }
737a332978bSJason Molenda       return num_restored > 0;
738a332978bSJason Molenda     }
739b9c1b51eSKate Stone   } else {
740b1127753SPavel Labath     Log *log(GetLog(GDBRLog::Thread | GDBRLog::Packets));
741b9c1b51eSKate Stone     if (log) {
742b9c1b51eSKate Stone       if (log->GetVerbose()) {
74328209d55SJim Ingham         StreamString strm;
74428209d55SJim Ingham         gdb_comm.DumpHistory(strm);
74563e5fb76SJonas Devlieghere         LLDB_LOGF(log,
74663e5fb76SJonas Devlieghere                   "error: failed to get packet sequence mutex, not sending "
747b9c1b51eSKate Stone                   "write all registers:\n%s",
748b9c1b51eSKate Stone                   strm.GetData());
749b9c1b51eSKate Stone       } else
75063e5fb76SJonas Devlieghere         LLDB_LOGF(log,
75163e5fb76SJonas Devlieghere                   "error: failed to get packet sequence mutex, not sending "
752b9c1b51eSKate Stone                   "write all registers");
753c3c0b0e5SGreg Clayton     }
754d451c1a8SGreg Clayton   }
75530fdc8d8SChris Lattner   return false;
75630fdc8d8SChris Lattner }
75730fdc8d8SChris Lattner 
ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,uint32_t num)758b9c1b51eSKate Stone uint32_t GDBRemoteRegisterContext::ConvertRegisterKindToRegisterNumber(
759b9c1b51eSKate Stone     lldb::RegisterKind kind, uint32_t num) {
7604fd77668SMuhammad Omair Javaid   return m_reg_info_sp->ConvertRegisterKindToRegisterNumber(kind, num);
76130fdc8d8SChris Lattner }
76230fdc8d8SChris Lattner 
AArch64SVEReconfigure()763e448ad78SMuhammad Omair Javaid bool GDBRemoteRegisterContext::AArch64SVEReconfigure() {
764e448ad78SMuhammad Omair Javaid   if (!m_reg_info_sp)
765e448ad78SMuhammad Omair Javaid     return false;
766e448ad78SMuhammad Omair Javaid 
767e448ad78SMuhammad Omair Javaid   const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("vg");
768e448ad78SMuhammad Omair Javaid   if (!reg_info)
769e448ad78SMuhammad Omair Javaid     return false;
770e448ad78SMuhammad Omair Javaid 
771e448ad78SMuhammad Omair Javaid   uint64_t fail_value = LLDB_INVALID_ADDRESS;
772e448ad78SMuhammad Omair Javaid   uint32_t vg_reg_num = reg_info->kinds[eRegisterKindLLDB];
773e448ad78SMuhammad Omair Javaid   uint64_t vg_reg_value = ReadRegisterAsUnsigned(vg_reg_num, fail_value);
774e448ad78SMuhammad Omair Javaid 
775e448ad78SMuhammad Omair Javaid   if (vg_reg_value != fail_value && vg_reg_value <= 32) {
776e448ad78SMuhammad Omair Javaid     const RegisterInfo *reg_info = m_reg_info_sp->GetRegisterInfo("p0");
777e448ad78SMuhammad Omair Javaid     if (!reg_info || vg_reg_value == reg_info->byte_size)
778e448ad78SMuhammad Omair Javaid       return false;
779e448ad78SMuhammad Omair Javaid 
780e448ad78SMuhammad Omair Javaid     if (m_reg_info_sp->UpdateARM64SVERegistersInfos(vg_reg_value)) {
781e448ad78SMuhammad Omair Javaid       // Make a heap based buffer that is big enough to store all registers
782e448ad78SMuhammad Omair Javaid       m_reg_data.SetData(std::make_shared<DataBufferHeap>(
783e448ad78SMuhammad Omair Javaid           m_reg_info_sp->GetRegisterDataByteSize(), 0));
784e448ad78SMuhammad Omair Javaid       m_reg_data.SetByteOrder(GetByteOrder());
785e448ad78SMuhammad Omair Javaid 
786e448ad78SMuhammad Omair Javaid       InvalidateAllRegisters();
787e448ad78SMuhammad Omair Javaid 
788e448ad78SMuhammad Omair Javaid       return true;
789e448ad78SMuhammad Omair Javaid     }
790e448ad78SMuhammad Omair Javaid   }
791e448ad78SMuhammad Omair Javaid 
792e448ad78SMuhammad Omair Javaid   return false;
793e448ad78SMuhammad Omair Javaid }
794e448ad78SMuhammad Omair Javaid 
UpdateARM64SVERegistersInfos(uint64_t vg)795e448ad78SMuhammad Omair Javaid bool GDBRemoteDynamicRegisterInfo::UpdateARM64SVERegistersInfos(uint64_t vg) {
796e448ad78SMuhammad Omair Javaid   // SVE Z register size is vg x 8 bytes.
797e448ad78SMuhammad Omair Javaid   uint32_t z_reg_byte_size = vg * 8;
798e448ad78SMuhammad Omair Javaid 
799e448ad78SMuhammad Omair Javaid   // SVE vector length has changed, accordingly set size of Z, P and FFR
800e448ad78SMuhammad Omair Javaid   // registers. Also invalidate register offsets it will be recalculated
801e448ad78SMuhammad Omair Javaid   // after SVE register size update.
802e448ad78SMuhammad Omair Javaid   for (auto &reg : m_regs) {
803e448ad78SMuhammad Omair Javaid     if (reg.value_regs == nullptr) {
804e448ad78SMuhammad Omair Javaid       if (reg.name[0] == 'z' && isdigit(reg.name[1]))
805e448ad78SMuhammad Omair Javaid         reg.byte_size = z_reg_byte_size;
806e448ad78SMuhammad Omair Javaid       else if (reg.name[0] == 'p' && isdigit(reg.name[1]))
807e448ad78SMuhammad Omair Javaid         reg.byte_size = vg;
808e448ad78SMuhammad Omair Javaid       else if (strcmp(reg.name, "ffr") == 0)
809e448ad78SMuhammad Omair Javaid         reg.byte_size = vg;
810e448ad78SMuhammad Omair Javaid     }
811e448ad78SMuhammad Omair Javaid     reg.byte_offset = LLDB_INVALID_INDEX32;
812e448ad78SMuhammad Omair Javaid   }
813e448ad78SMuhammad Omair Javaid 
814e448ad78SMuhammad Omair Javaid   // Re-calculate register offsets
815e448ad78SMuhammad Omair Javaid   ConfigureOffsets();
816e448ad78SMuhammad Omair Javaid   return true;
817e448ad78SMuhammad Omair Javaid }
818