[Lldb-commits] [lldb] [lldb][RISCV] Handle subsets of CSRs in RV32 core dump images (PR #142932)

Alexey Merzlyakov via lldb-commits lldb-commits at lists.llvm.org
Wed Apr 29 03:16:24 PDT 2026


================
@@ -7,75 +7,333 @@
 //===----------------------------------------------------------------------===//
 
 #include "RegisterContextPOSIXCore_riscv32.h"
+
+#include "lldb/Core/Debugger.h"
 #include "lldb/Utility/DataBufferHeap.h"
 
+#define GPR_OFFSET(idx) ((idx) * sizeof(uint32_t))
+#define FPR_OFFSET(idx) ((idx) * sizeof(uint32_t))
+#define CSR_OFFSET(idx) ((idx) * sizeof(uint32_t))
+
+#define DECLARE_REGISTER_INFOS_RISCV32_STRUCT
+#include "Plugins/Process/Utility/RegisterInfos_riscv32.h"
+#undef DECLARE_REGISTER_INFOS_RISCV32_STRUCT
+
 using namespace lldb_private;
 
+static std::vector<uint32_t> CopyRegisterListToVector(const uint32_t *regs) {
+  if (!regs)
+    return {};
+
+  const uint32_t *end = regs;
+  while (*end != LLDB_INVALID_REGNUM)
+    ++end;
+
+  return std::vector<uint32_t>(regs, end);
+}
+
 std::unique_ptr<RegisterContextCorePOSIX_riscv32>
 RegisterContextCorePOSIX_riscv32::Create(Thread &thread, const ArchSpec &arch,
                                          const DataExtractor &gpregset,
                                          llvm::ArrayRef<CoreNote> notes) {
-  Flags opt_regsets = RegisterInfoPOSIX_riscv32::eRegsetMaskDefault;
-
   return std::unique_ptr<RegisterContextCorePOSIX_riscv32>(
       new RegisterContextCorePOSIX_riscv32(
-          thread,
-          std::make_unique<RegisterInfoPOSIX_riscv32>(arch, opt_regsets),
+          thread, std::make_unique<RegisterInfoPOSIXDynamic_riscv32>(arch),
           gpregset, notes));
 }
 
 RegisterContextCorePOSIX_riscv32::RegisterContextCorePOSIX_riscv32(
-    Thread &thread, std::unique_ptr<RegisterInfoPOSIX_riscv32> register_info,
+    Thread &thread,
+    std::unique_ptr<RegisterInfoPOSIXDynamic_riscv32> register_info,
     const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
-    : RegisterContextPOSIX_riscv32(thread, std::move(register_info)) {
+    : RegisterContext(thread, 0), m_reg_infos_up(std::move(register_info)) {
+  // Compute the maximum register counts for GPR, FPR, and CSR.
+  constexpr uint32_t k_num_gpr_registers =
+      std::size(g_register_infos_riscv32_gpr);
+  constexpr uint32_t k_num_fpr_registers =
+      std::size(g_register_infos_riscv32_fpr);
+  constexpr uint32_t k_num_csr_registers =
+      std::size(g_register_infos_riscv32_csr);
 
-  m_gpr.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
-                                                 gpregset.GetByteSize()));
-  m_gpr.SetByteOrder(gpregset.GetByteOrder());
+  std::vector<DynamicRegisterInfo::Register> registers;
+  uint32_t byte_offset = 0;
 
-  if (m_register_info_up->IsFPPresent()) {
-    ArchSpec arch = m_register_info_up->GetTargetArchitecture();
-    m_fpr = getRegset(notes, arch.GetTriple(), FPR_Desc);
+  // Build dynamic register information for GPR.
+  const lldb_private::ConstString gpr_set("GPR");
+  m_gpregset.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
+                                                      gpregset.GetByteSize()));
+  if (m_gpregset.GetByteSize() >= g_register_infos_riscv32_gpr[0].byte_size) {
+    // GPR is available.
+    assert((m_gpregset.GetByteSize() /
+            g_register_infos_riscv32_gpr[0].byte_size) == k_num_gpr_registers &&
+           "GPR has the wrong number of registers!");
+    m_gpregset.SetByteOrder(gpregset.GetByteOrder());
+    for (const auto &gpr : g_register_infos_riscv32_gpr) {
+      registers.push_back(BuildDynamicRegister(gpr, gpr_set, byte_offset));
+      byte_offset += gpr.byte_size;
+    }
   }
+
+  // Build dynamic register information for FPR.
+  const lldb_private::ConstString fpr_set("FPR");
+  m_fpregset = getRegset(
+      notes, m_reg_infos_up->GetTargetArchitecture().GetTriple(), FPR_Desc);
+  if (m_fpregset.GetByteSize() >= g_register_infos_riscv32_fpr[0].byte_size) {
+    // FPR is available.
+    assert((m_fpregset.GetByteSize() /
+            g_register_infos_riscv32_fpr[0].byte_size) == k_num_fpr_registers &&
+           "FPR has the wrong number of registers!");
+    m_fpregset.SetByteOrder(lldb::eByteOrderLittle);
+    for (const auto &fpr : g_register_infos_riscv32_fpr) {
+      registers.push_back(BuildDynamicRegister(fpr, fpr_set, byte_offset));
+      byte_offset += fpr.byte_size;
+    }
+  }
+
+  // Build dynamic register information for CSR.
+  const lldb_private::ConstString csr_set("CSR");
+  m_csregset =
+      getRegset(notes, m_reg_infos_up->GetTargetArchitecture().GetTriple(),
+                RISCV32_CSREGMAP_Desc);
+  if (m_csregset.GetByteSize() >=
+      (sizeof(csr_kv_t::addr) + sizeof(csr_kv_t::val))) {
+    // CSR is available.
+    m_csregset.SetByteOrder(lldb::eByteOrderLittle);
+    lldb::offset_t offset = 0;
+    while (m_csregset.BytesLeft(offset)) {
+      uint32_t csr_addr = m_csregset.GetU32(&offset);
+      if (m_csregset_regnums.size() == k_num_csr_registers) {
----------------
AlexeyMerzlyakov wrote:

It seem that m_csregset_regnums is used only inside this creator function logic only. If so, do we need m_csregset_regnums to be the class member or it is better to be just local variable here to save the object's memory?

https://github.com/llvm/llvm-project/pull/142932


More information about the lldb-commits mailing list