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 ®info = 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 ®_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 ®_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 ® : 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