LLDB mainline
RegisterContextPOSIXCore_riscv32.cpp
Go to the documentation of this file.
1//===-- RegisterContextPOSIXCore_riscv32.cpp ------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10
11#include "lldb/Core/Debugger.h"
13
14#define GPR_OFFSET(idx) ((idx) * sizeof(uint32_t))
15#define FPR_OFFSET(idx) ((idx) * sizeof(uint32_t))
16
17#define DECLARE_REGISTER_INFOS_RISCV32_STRUCT
19#undef DECLARE_REGISTER_INFOS_RISCV32_STRUCT
20
21using namespace lldb_private;
22
23static std::vector<uint32_t> CopyRegisterListToVector(const uint32_t *regs) {
24 if (!regs)
25 return {};
26
27 const uint32_t *end = regs;
28 while (*end != LLDB_INVALID_REGNUM)
29 ++end;
30
31 return std::vector<uint32_t>(regs, end);
32}
33
34std::unique_ptr<RegisterContextCorePOSIX_riscv32>
36 const DataExtractor &gpregset,
37 llvm::ArrayRef<CoreNote> notes) {
38 return std::unique_ptr<RegisterContextCorePOSIX_riscv32>(
40 thread, std::make_unique<RegisterInfoPOSIXDynamic_riscv32>(arch),
41 gpregset, notes));
42}
43
45 Thread &thread,
46 std::unique_ptr<RegisterInfoPOSIXDynamic_riscv32> register_info,
47 const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
48 : RegisterContext(thread, 0), m_reg_infos_up(std::move(register_info)) {
49 // Compute the maximum register counts for GPR, FPR, and CSR.
50 constexpr uint32_t k_num_gpr_registers =
51 std::size(g_register_infos_riscv32_gpr);
52 constexpr uint32_t k_num_fpr_registers =
53 std::size(g_register_infos_riscv32_fpr);
54 constexpr uint32_t k_num_csr_registers =
55 std::size(g_register_infos_riscv32_csr);
56 const ArchSpec &target_arch = m_reg_infos_up->GetTargetArchitecture();
57 const llvm::Triple triple = target_arch.GetTriple();
58 const lldb::ByteOrder byte_order = target_arch.GetByteOrder();
59
60 std::vector<DynamicRegisterInfo::Register> registers;
61 uint32_t byte_offset = 0;
62
63 // Build dynamic register information for GPR.
64 const lldb_private::ConstString gpr_set("GPR");
65 m_gpregset.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
66 gpregset.GetByteSize()));
67 if (m_gpregset.GetByteSize() >= g_register_infos_riscv32_gpr[0].byte_size) {
68 // GPR is available.
69 assert((m_gpregset.GetByteSize() /
70 g_register_infos_riscv32_gpr[0].byte_size) == k_num_gpr_registers &&
71 "GPR has the wrong number of registers!");
72 m_gpregset.SetByteOrder(gpregset.GetByteOrder());
73 for (const auto &gpr : g_register_infos_riscv32_gpr) {
74 registers.push_back(BuildDynamicRegister(gpr, gpr_set, byte_offset));
75 byte_offset += gpr.byte_size;
76 }
77 }
78
79 // Build dynamic register information for FPR.
80 const lldb_private::ConstString fpr_set("FPR");
81 m_fpregset = getRegset(notes, triple, FPR_Desc);
82 if (m_fpregset.GetByteSize() >= g_register_infos_riscv32_fpr[0].byte_size) {
83 // FPR is available.
84 assert((m_fpregset.GetByteSize() /
85 g_register_infos_riscv32_fpr[0].byte_size) == k_num_fpr_registers &&
86 "FPR has the wrong number of registers!");
87 m_fpregset.SetByteOrder(byte_order);
88 for (const auto &fpr : g_register_infos_riscv32_fpr) {
89 registers.push_back(BuildDynamicRegister(fpr, fpr_set, byte_offset));
90 byte_offset += fpr.byte_size;
91 }
92 }
93
94 // Build dynamic register information for CSR.
95 const lldb_private::ConstString csr_set("CSR");
97 if (m_csregset.GetByteSize() >=
98 (sizeof(csr_kv_t::addr) + sizeof(csr_kv_t::val))) {
99 // CSR is available.
100 m_csregset.SetByteOrder(byte_order);
101 lldb::offset_t offset = 0;
102 std::vector<uint32_t> csregset_regnums = {};
103 while (m_csregset.BytesLeft(offset)) {
104 uint32_t csr_addr = m_csregset.GetU32(&offset);
105 if (csregset_regnums.size() == k_num_csr_registers) {
107 llvm::formatv("parsed the permissible number of CSRs {0:x} but "
108 "NT_CSREGMAP has more; skipping the remaining CSRs",
110 break;
111 }
112 if (llvm::is_contained(csregset_regnums, csr_addr)) {
114 llvm::formatv("encountered a duplicate CSR while parsing "
115 "NT_CSREGMAP: {0}; skipping",
116 g_register_infos_riscv32_csr[csr_addr].name));
117 } else {
118 csregset_regnums.push_back(csr_addr);
119 const RegisterInfo &csr = g_register_infos_riscv32_csr[csr_addr];
120 registers.push_back(BuildDynamicRegister(csr, csr_set, byte_offset));
121 byte_offset += csr.byte_size;
122 }
123 // Consume and skip the CSR value to advance to the next entry.
124 (void)m_csregset.GetU32(&offset);
125 }
126 }
127
128 m_reg_infos_up->SetRegisterInfo(std::move(registers));
129}
130
132
134
136 return m_reg_infos_up->GetRegisterCount();
137}
138
141 if (reg < GetRegisterCount())
142 return &m_reg_infos_up->GetRegisterInfo()[static_cast<uint32_t>(reg)];
143 return nullptr;
144}
145
147 return m_reg_infos_up->GetRegisterSetCount();
148}
149
152 return m_reg_infos_up->GetRegisterSet(static_cast<uint32_t>(set));
153}
154
156 const RegisterInfo *reg_info, RegisterValue &value) {
157 const lldb_private::RegisterInfo *dyn_reg_info;
158 const uint8_t *src = nullptr;
159 if ((dyn_reg_info = m_reg_infos_up->GetRegisterInfo(reg_info->name))) {
160 lldb::offset_t offset = dyn_reg_info->byte_offset;
161 if (IsGPR(dyn_reg_info->kinds[lldb::eRegisterKindLLDB])) {
162 // clang-format off
163 //
164 // |____| |_______________|
165 // | | src -> | |
166 // | pc | <- dyn_reg_info->byte_offset = 0 | m_gpregset[0] | uint32_t
167 // |____| offset = 0 -> |_______________|
168 // | | | |
169 // | x1 | | m_gpregset[4] | uint32_t
170 // |____| |_______________|
171 // .. ..
172 // |____| |_______________|
173 // | | | |
174 // | xn | <- dyn_reg_info->byte_offset offset -> | m_gpregset[n] | uint32_t
175 // |____| |_______________|
176 // | | | |
177 // .. ..
178 //
179 // clang-format on
180 src = m_gpregset.GetDataStart();
181 } else if (IsFPR(dyn_reg_info->kinds[lldb::eRegisterKindLLDB])) {
182 // clang-format off
183 //
184 // |____|
185 // | |
186 // | pc | <- dyn_reg_info->byte_offset = 0
187 // |____|
188 // | |
189 // | x1 |
190 // |____|
191 // ..
192 // |____|
193 // | |
194 // | x0 |
195 // |____| |_______________|
196 // | | src -> | |
197 // | f0 | | m_fpregset[0] | uint32_t
198 // |____| offset = 0 -> |_______________|
199 // | | | |
200 // | f1 | | m_fpregset[4] | uint32_t
201 // |____| |_______________|
202 // .. ..
203 // |____| |_______________|
204 // | | | |
205 // | fn | <- dyn_reg_info->byte_offset offset -> | m_fpregset[n] | uint32_t
206 // |____| |_______________|
207 // | | | |
208 // .. ..
209 //
210 // clang-format on
211 src = m_fpregset.GetDataStart();
212 offset -= (g_register_infos_riscv32_gpr[0].byte_size *
213 m_reg_infos_up->GetGPRSize());
214 } else if (IsCSR(dyn_reg_info->kinds[lldb::eRegisterKindLLDB])) {
215 // clang-format off
216 //
217 // |______|
218 // | |
219 // | pc | <- dyn_reg_info->byte_offset = 0
220 // |______|
221 // | |
222 // | x1 |
223 // |______|
224 // ..
225 // |______|
226 // | |
227 // | x0 |
228 // |______|
229 // | |
230 // | f0 |
231 // |______|
232 // | |
233 // | f1 |
234 // |______|
235 // ..
236 // |______|
237 // | |
238 // | f31 |
239 // |______| |________________|
240 // | | src -> | |
241 // | | csr0::addr -> | m_csregset[00] | uint32_t
242 // | | offset = 0 -> | |
243 // | csr0 | |----------------|
244 // | | | |
245 // | | csr0::val -> | m_csregset[04] | uint32_t
246 // |______| |________________|
247 // | | | |
248 // | | csr1::addr -> | m_csregset[08] | uint32_t
249 // | | | |
250 // | csr1 | |----------------|
251 // | | | |
252 // | | csr1::val -> | m_csregset[12] | uint32_t
253 // |______| |________________|
254 // .. ..
255 // |______| |________________|
256 // | | | |
257 // | | csrn::addr -> | m_csregset[..] | uint32_t
258 // | | | |
259 // | csrn | |----------------|
260 // | | csrn::val -> | |
261 // | | | m_csregset[..] | uint32_t
262 // |______| offset -> |________________|
263 // | | | |
264 // .. ..
265 //
266 // clang-format on
267 src = m_csregset.GetDataStart();
268 offset -= ((g_register_infos_riscv32_gpr[0].byte_size *
269 m_reg_infos_up->GetGPRSize()) +
270 (g_register_infos_riscv32_fpr[0].byte_size *
271 m_reg_infos_up->GetFPRSize()));
272 offset *= 2;
273 offset += dyn_reg_info->byte_size;
274 } else {
275 return false;
276 }
277
279 value.SetFromMemoryData(*dyn_reg_info, src + offset,
280 dyn_reg_info->byte_size, lldb::eByteOrderLittle,
281 error);
282 return error.Success();
283 } else {
284 return false;
285 }
286}
287
289 const RegisterInfo *reg_info, const RegisterValue &value) {
290 return false;
291}
292
294 if (llvm::StringRef(
295 GetRegisterSet(m_reg_infos_up->GetRegisterSetFromRegisterIndex(reg))
296 ->name)
297 .equals_insensitive(llvm::StringRef("GPR")))
298 return true;
299 return false;
300}
301
303 if (llvm::StringRef(
304 GetRegisterSet(m_reg_infos_up->GetRegisterSetFromRegisterIndex(reg))
305 ->name)
306 .equals_insensitive(llvm::StringRef("FPR")))
307 return true;
308 return false;
309}
310
312 if (llvm::StringRef(
313 GetRegisterSet(m_reg_infos_up->GetRegisterSetFromRegisterIndex(reg))
314 ->name)
315 .equals_insensitive(llvm::StringRef("CSR")))
316 return true;
317 return false;
318}
319
322 const lldb_private::RegisterInfo &reg_info,
323 const lldb_private::ConstString &set_name, uint32_t byte_offset) {
327 set_name,
328 reg_info.byte_size,
329 byte_offset,
330 reg_info.encoding,
331 reg_info.format,
338 /*value_reg_offset=*/0,
339 reg_info.flags_type};
340}
static llvm::raw_ostream & error(Stream &strm)
const size_t k_num_gpr_registers
const size_t k_num_csr_registers
const size_t k_num_fpr_registers
static std::vector< uint32_t > CopyRegisterListToVector(const uint32_t *regs)
const lldb_private::RegisterInfo * GetRegisterInfoAtIndex(size_t reg) override
static std::unique_ptr< RegisterContextCorePOSIX_riscv32 > Create(lldb_private::Thread &thread, const lldb_private::ArchSpec &arch, const lldb_private::DataExtractor &gpregset, llvm::ArrayRef< lldb_private::CoreNote > notes)
const lldb_private::RegisterSet * GetRegisterSet(size_t set) override
bool WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value) override
RegisterContextCorePOSIX_riscv32(lldb_private::Thread &thread, std::unique_ptr< RegisterInfoPOSIXDynamic_riscv32 > register_info, const lldb_private::DataExtractor &gpregset, llvm::ArrayRef< lldb_private::CoreNote > notes)
bool ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value) override
std::unique_ptr< RegisterInfoPOSIXDynamic_riscv32 > m_reg_infos_up
lldb_private::DynamicRegisterInfo::Register BuildDynamicRegister(const lldb_private::RegisterInfo &reg_info, const lldb_private::ConstString &set_name, uint32_t byte_offset)
An architecture specification class.
Definition ArchSpec.h:32
llvm::Triple & GetTriple()
Architecture triple accessor.
Definition ArchSpec.h:460
lldb::ByteOrder GetByteOrder() const
Returns the byte order for the architecture specification.
Definition ArchSpec.cpp:739
A uniqued constant string class.
Definition ConstString.h:40
An data extractor class.
virtual uint64_t GetByteSize() const
Get the number of bytes contained in this object.
const uint8_t * GetDataStart() const
Get the data start pointer.
lldb::ByteOrder GetByteOrder() const
Get the current byte order value.
static void ReportWarning(std::string message, std::optional< lldb::user_id_t > debugger_id=std::nullopt, std::once_flag *once=nullptr)
Report warning events.
RegisterContext(Thread &thread, uint32_t concrete_frame_idx)
uint32_t SetFromMemoryData(const RegisterInfo &reg_info, const void *src, uint32_t src_len, lldb::ByteOrder src_byte_order, Status &error)
An error handling class.
Definition Status.h:118
#define LLDB_INVALID_REGNUM
A class that represents a running process on the host machine.
constexpr RegsetDesc RISCV32_CSREGMAP_Desc[]
DataExtractor getRegset(llvm::ArrayRef< CoreNote > Notes, const llvm::Triple &Triple, llvm::ArrayRef< RegsetDesc > RegsetDescs)
constexpr RegsetDesc FPR_Desc[]
uint64_t offset_t
Definition lldb-types.h:85
ByteOrder
Byte ordering definitions.
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
@ eRegisterKindLLDB
lldb's internal register numbers
@ eRegisterKindDWARF
the register numbers seen DWARF
@ eRegisterKindEHFrame
the register numbers seen in eh_frame
@ eRegisterKindProcessPlugin
num used by the process plugin - e.g.
Every register is described in detail including its name, alternate name (optional),...
lldb::Encoding encoding
Encoding of the register bits.
const char * alt_name
Alternate name of this register, can be NULL.
uint32_t * value_regs
List of registers (terminated with LLDB_INVALID_REGNUM).
uint32_t byte_offset
The byte offset in the register context data where this register's value is found.
uint32_t byte_size
Size in bytes of the register.
uint32_t kinds[lldb::kNumRegisterKinds]
Holds all of the various register numbers for all register kinds.
const RegisterFlags * flags_type
If not nullptr, a type defined by XML descriptions.
const char * name
Name of this register, can't be NULL.
lldb::Format format
Default display format.
uint32_t * invalidate_regs
List of registers (terminated with LLDB_INVALID_REGNUM).
Registers are grouped into register sets.
const char * name
Name of this register set.