[Lldb-commits] [lldb] 096ab51 - [lldb][MachO] MachO corefile support for riscv32 binaries (#137092)
via lldb-commits
lldb-commits at lists.llvm.org
Wed Apr 23 22:10:19 PDT 2025
Author: Jason Molenda
Date: 2025-04-23T22:10:15-07:00
New Revision: 096ab51de03437e38f97a48b8f2d453fb903414a
URL: https://github.com/llvm/llvm-project/commit/096ab51de03437e38f97a48b8f2d453fb903414a
DIFF: https://github.com/llvm/llvm-project/commit/096ab51de03437e38f97a48b8f2d453fb903414a.diff
LOG: [lldb][MachO] MachO corefile support for riscv32 binaries (#137092)
Add support for reading a macho corefile with CPU_TYPE_RISCV and the
riscv32 general purpose register file. I added code for the floating
point and exception registers too, but haven't exercised this. If we
start putting the full CSR register bank in a riscv corefile, it'll be
in separate 4k byte chunks, but I don't have a corefile to test against
that so I haven't written the code to read it.
The RegisterContextDarwin_riscv32 is copied & in the style of the other
RegisterContextDarwin classes; it's not the first choice I would make
for representing this, but it wasn't worth changing for this cputype.
rdar://145014653
Added:
lldb/source/Plugins/Process/Utility/RegisterContextDarwin_riscv32.cpp
lldb/source/Plugins/Process/Utility/RegisterContextDarwin_riscv32.h
lldb/test/API/macosx/riscv32-corefile/Makefile
lldb/test/API/macosx/riscv32-corefile/TestRV32MachOCorefile.py
lldb/test/API/macosx/riscv32-corefile/create-empty-riscv-corefile.cpp
Modified:
lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
lldb/source/Plugins/Process/Utility/CMakeLists.txt
Removed:
################################################################################
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index f31b56b9f81e6..9d5e0f886a4a5 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -12,6 +12,7 @@
#include "Plugins/Process/Utility/RegisterContextDarwin_arm.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_arm64.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_i386.h"
+#include "Plugins/Process/Utility/RegisterContextDarwin_riscv32.h"
#include "Plugins/Process/Utility/RegisterContextDarwin_x86_64.h"
#include "lldb/Core/Debugger.h"
#include "lldb/Core/Module.h"
@@ -769,6 +770,147 @@ class RegisterContextDarwin_arm64_Mach : public RegisterContextDarwin_arm64 {
}
};
+class RegisterContextDarwin_riscv32_Mach
+ : public RegisterContextDarwin_riscv32 {
+public:
+ RegisterContextDarwin_riscv32_Mach(lldb_private::Thread &thread,
+ const DataExtractor &data)
+ : RegisterContextDarwin_riscv32(thread, 0) {
+ SetRegisterDataFrom_LC_THREAD(data);
+ }
+
+ void InvalidateAllRegisters() override {
+ // Do nothing... registers are always valid...
+ }
+
+ void SetRegisterDataFrom_LC_THREAD(const DataExtractor &data) {
+ lldb::offset_t offset = 0;
+ SetError(GPRRegSet, Read, -1);
+ SetError(FPURegSet, Read, -1);
+ SetError(EXCRegSet, Read, -1);
+ SetError(CSRRegSet, Read, -1);
+ bool done = false;
+ while (!done) {
+ int flavor = data.GetU32(&offset);
+ uint32_t count = data.GetU32(&offset);
+ lldb::offset_t next_thread_state = offset + (count * 4);
+ switch (flavor) {
+ case GPRRegSet:
+ // x0-x31 + pc
+ if (count >= 32) {
+ for (uint32_t i = 0; i < 32; ++i)
+ ((uint32_t *)&gpr.x0)[i] = data.GetU32(&offset);
+ gpr.pc = data.GetU32(&offset);
+ SetError(GPRRegSet, Read, 0);
+ }
+ offset = next_thread_state;
+ break;
+ case FPURegSet: {
+ // f0-f31 + fcsr
+ if (count >= 32) {
+ for (uint32_t i = 0; i < 32; ++i)
+ ((uint32_t *)&fpr.f0)[i] = data.GetU32(&offset);
+ fpr.fcsr = data.GetU32(&offset);
+ SetError(FPURegSet, Read, 0);
+ }
+ }
+ offset = next_thread_state;
+ break;
+ case EXCRegSet:
+ if (count == 3) {
+ exc.exception = data.GetU32(&offset);
+ exc.fsr = data.GetU32(&offset);
+ exc.far = data.GetU32(&offset);
+ SetError(EXCRegSet, Read, 0);
+ }
+ offset = next_thread_state;
+ break;
+ default:
+ done = true;
+ break;
+ }
+ }
+ }
+
+ static bool Create_LC_THREAD(Thread *thread, Stream &data) {
+ RegisterContextSP reg_ctx_sp(thread->GetRegisterContext());
+ if (reg_ctx_sp) {
+ RegisterContext *reg_ctx = reg_ctx_sp.get();
+
+ data.PutHex32(GPRRegSet); // Flavor
+ data.PutHex32(GPRWordCount);
+ PrintRegisterValue(reg_ctx, "x0", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x1", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x2", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x3", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x4", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x5", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x6", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x7", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x8", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x9", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x10", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x11", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x12", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x13", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x14", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x15", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x16", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x17", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x18", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x19", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x20", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x21", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x22", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x23", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x24", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x25", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x26", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x27", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x28", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x29", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x30", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "x31", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "pc", nullptr, 4, data);
+ data.PutHex32(0); // uint32_t pad at the end
+
+ // Write out the EXC registers
+ data.PutHex32(EXCRegSet);
+ data.PutHex32(EXCWordCount);
+ PrintRegisterValue(reg_ctx, "exception", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "fsr", nullptr, 4, data);
+ PrintRegisterValue(reg_ctx, "far", nullptr, 4, data);
+ return true;
+ }
+ return false;
+ }
+
+protected:
+ int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) override { return -1; }
+
+ int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpu) override { return -1; }
+
+ int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) override { return -1; }
+
+ int DoReadCSR(lldb::tid_t tid, int flavor, CSR &csr) override { return -1; }
+
+ int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) override {
+ return 0;
+ }
+
+ int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpu) override {
+ return 0;
+ }
+
+ int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) override {
+ return 0;
+ }
+
+ int DoWriteCSR(lldb::tid_t tid, int flavor, const CSR &csr) override {
+ return 0;
+ }
+};
+
static uint32_t MachHeaderSizeFromMagic(uint32_t magic) {
switch (magic) {
case MH_MAGIC:
@@ -5827,6 +5969,11 @@ ObjectFileMachO::GetThreadContextAtIndex(uint32_t idx,
reg_ctx_sp =
std::make_shared<RegisterContextDarwin_x86_64_Mach>(thread, data);
break;
+
+ case llvm::MachO::CPU_TYPE_RISCV:
+ reg_ctx_sp =
+ std::make_shared<RegisterContextDarwin_riscv32_Mach>(thread, data);
+ break;
}
}
}
@@ -6695,6 +6842,11 @@ bool ObjectFileMachO::SaveCore(const lldb::ProcessSP &process_sp,
RegisterContextDarwin_x86_64_Mach::Create_LC_THREAD(
thread_sp.get(), LC_THREAD_datas[thread_idx]);
break;
+
+ case llvm::MachO::CPU_TYPE_RISCV:
+ RegisterContextDarwin_riscv32_Mach::Create_LC_THREAD(
+ thread_sp.get(), LC_THREAD_datas[thread_idx]);
+ break;
}
}
}
diff --git a/lldb/source/Plugins/Process/Utility/CMakeLists.txt b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
index f269f5d7d4d74..d29605fddd5cb 100644
--- a/lldb/source/Plugins/Process/Utility/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
@@ -20,6 +20,7 @@ add_lldb_library(lldbPluginProcessUtility
RegisterContextDarwin_arm.cpp
RegisterContextDarwin_arm64.cpp
RegisterContextDarwin_i386.cpp
+ RegisterContextDarwin_riscv32.cpp
RegisterContextDarwin_x86_64.cpp
RegisterContextDummy.cpp
RegisterContextFreeBSD_i386.cpp
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_riscv32.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_riscv32.cpp
new file mode 100644
index 0000000000000..14f5bc3ea8c49
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_riscv32.cpp
@@ -0,0 +1,1313 @@
+//===-- RegisterContextDarwin_riscv32.cpp
+//------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/DataExtractor.h"
+#include "lldb/Utility/Endian.h"
+#include "lldb/Utility/Log.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Scalar.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Compiler.h"
+
+#include <cstddef>
+
+#include <memory>
+
+#include "RegisterContextDarwin_riscv32.h"
+#include "Utility/RISCV_DWARF_Registers.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+enum {
+ gpr_x0 = 0,
+ gpr_x1,
+ gpr_x2,
+ gpr_x3,
+ gpr_x4,
+ gpr_x5,
+ gpr_x6,
+ gpr_x7,
+ gpr_x8,
+ gpr_x9,
+ gpr_x10,
+ gpr_x11,
+ gpr_x12,
+ gpr_x13,
+ gpr_x14,
+ gpr_x15,
+ gpr_x16,
+ gpr_x17,
+ gpr_x18,
+ gpr_x19,
+ gpr_x20,
+ gpr_x21,
+ gpr_x22,
+ gpr_x23,
+ gpr_x24,
+ gpr_x25,
+ gpr_x26,
+ gpr_x27,
+ gpr_x28,
+ gpr_x29,
+ gpr_x30,
+ gpr_x31,
+ gpr_pc,
+
+ fpr_f0,
+ fpr_f1,
+ fpr_f2,
+ fpr_f3,
+ fpr_f4,
+ fpr_f5,
+ fpr_f6,
+ fpr_f7,
+ fpr_f8,
+ fpr_f9,
+ fpr_f10,
+ fpr_f11,
+ fpr_f12,
+ fpr_f13,
+ fpr_f14,
+ fpr_f15,
+ fpr_f16,
+ fpr_f17,
+ fpr_f18,
+ fpr_f19,
+ fpr_f20,
+ fpr_f21,
+ fpr_f22,
+ fpr_f23,
+ fpr_f24,
+ fpr_f25,
+ fpr_f26,
+ fpr_f27,
+ fpr_f28,
+ fpr_f29,
+ fpr_f30,
+ fpr_f31,
+ fpr_fcsr,
+
+ exc_exception,
+ exc_fsr,
+ exc_far,
+
+ csr_bank,
+
+ k_num_registers
+};
+
+/* clang-format off */
+#define GPR_OFFSET(reg) \
+ (LLVM_EXTENSION offsetof(RegisterContextDarwin_riscv32::GPR, reg))
+#define FPU_OFFSET(reg) \
+ (LLVM_EXTENSION offsetof(RegisterContextDarwin_riscv32::FPU, reg) + \
+ sizeof(RegisterContextDarwin_riscv32::GPR))
+#define EXC_OFFSET(reg) \
+ (LLVM_EXTENSION offsetof(RegisterContextDarwin_riscv32::EXC, reg) + \
+ sizeof(RegisterContextDarwin_riscv32::GPR) + \
+ sizeof(RegisterContextDarwin_riscv32::FPU))
+
+// These macros will auto define the register name, alt name, register size,
+// register offset, encoding, format and native register. This ensures that the
+// register state structures are defined correctly and have the correct sizes
+// and offsets.
+#define DEFINE_GPR_ABI(reg, canon) \
+ #reg, #canon, \
+ sizeof(((RegisterContextDarwin_riscv32::GPR *)nullptr)->canon), \
+ GPR_OFFSET(canon), eEncodingUint, eFormatHex
+#define DEFINE_GPR(reg) \
+ #reg, nullptr, \
+ sizeof(((RegisterContextDarwin_riscv32::GPR *)nullptr)->reg), \
+ GPR_OFFSET(reg), eEncodingUint, eFormatHex
+#define DEFINE_FPU_ABI(reg, canon) \
+ #reg, #canon, \
+ sizeof(((RegisterContextDarwin_riscv32::FPU *)nullptr)->canon), \
+ FPU_OFFSET(canon), eEncodingUint, eFormatHex
+#define DEFINE_FPU(reg) \
+ #reg, nullptr, \
+ sizeof(((RegisterContextDarwin_riscv32::FPU *)nullptr)->reg), \
+ FPU_OFFSET(reg), eEncodingUint, eFormatHex
+#define DEFINE_EXC(reg) \
+ #reg, nullptr, \
+ sizeof(((RegisterContextDarwin_riscv32::EXC *)nullptr)->reg), \
+ EXC_OFFSET(reg), eEncodingUint, eFormatHex
+#define REG_CONTEXT_SIZE \
+ (sizeof(RegisterContextDarwin_riscv32::GPR) + \
+ sizeof(RegisterContextDarwin_riscv32::FPU) + \
+ sizeof(RegisterContextDarwin_riscv32::EXC) + \
+ sizeof(RegisterContextDarwin_riscv32::CSR))
+/* clang-format on */
+
+static RegisterInfo g_register_infos[] = {
+ {
+ DEFINE_GPR_ABI(zero, x0),
+ {riscv_dwarf::dwarf_gpr_x0, riscv_dwarf::dwarf_gpr_x0,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x0},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(ra, x1),
+ {riscv_dwarf::dwarf_gpr_x1, riscv_dwarf::dwarf_gpr_x1,
+ LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, gpr_x1},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(sp, x2),
+ {riscv_dwarf::dwarf_gpr_x2, riscv_dwarf::dwarf_gpr_x2,
+ LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, gpr_x2},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(gp, x3),
+ {riscv_dwarf::dwarf_gpr_x3, riscv_dwarf::dwarf_gpr_x3,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x3},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(tp, x4),
+ {riscv_dwarf::dwarf_gpr_x4, riscv_dwarf::dwarf_gpr_x4,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x4},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(t0, x5),
+ {riscv_dwarf::dwarf_gpr_x5, riscv_dwarf::dwarf_gpr_x5,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x5},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(t1, x6),
+ {riscv_dwarf::dwarf_gpr_x6, riscv_dwarf::dwarf_gpr_x6,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x6},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(t2, x7),
+ {riscv_dwarf::dwarf_gpr_x7, riscv_dwarf::dwarf_gpr_x7,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x7},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(fp, x8),
+ {riscv_dwarf::dwarf_gpr_x8, riscv_dwarf::dwarf_gpr_x8,
+ LLDB_REGNUM_GENERIC_FP, LLDB_INVALID_REGNUM, gpr_x8},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s1, x9),
+ {riscv_dwarf::dwarf_gpr_x9, riscv_dwarf::dwarf_gpr_x9,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x9},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(a0, x10),
+ {riscv_dwarf::dwarf_gpr_x10, riscv_dwarf::dwarf_gpr_x10,
+ LLDB_REGNUM_GENERIC_ARG1, LLDB_INVALID_REGNUM, gpr_x10},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(a1, x11),
+ {riscv_dwarf::dwarf_gpr_x11, riscv_dwarf::dwarf_gpr_x11,
+ LLDB_REGNUM_GENERIC_ARG2, LLDB_INVALID_REGNUM, gpr_x11},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(a2, x12),
+ {riscv_dwarf::dwarf_gpr_x12, riscv_dwarf::dwarf_gpr_x12,
+ LLDB_REGNUM_GENERIC_ARG3, LLDB_INVALID_REGNUM, gpr_x12},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(a3, x13),
+ {riscv_dwarf::dwarf_gpr_x13, riscv_dwarf::dwarf_gpr_x13,
+ LLDB_REGNUM_GENERIC_ARG4, LLDB_INVALID_REGNUM, gpr_x13},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(a4, x14),
+ {riscv_dwarf::dwarf_gpr_x14, riscv_dwarf::dwarf_gpr_x14,
+ LLDB_REGNUM_GENERIC_ARG5, LLDB_INVALID_REGNUM, gpr_x14},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(a5, x15),
+ {riscv_dwarf::dwarf_gpr_x15, riscv_dwarf::dwarf_gpr_x15,
+ LLDB_REGNUM_GENERIC_ARG6, LLDB_INVALID_REGNUM, gpr_x15},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(a6, x16),
+ {riscv_dwarf::dwarf_gpr_x16, riscv_dwarf::dwarf_gpr_x16,
+ LLDB_REGNUM_GENERIC_ARG7, LLDB_INVALID_REGNUM, gpr_x16},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(a7, x17),
+ {riscv_dwarf::dwarf_gpr_x17, riscv_dwarf::dwarf_gpr_x17,
+ LLDB_REGNUM_GENERIC_ARG8, LLDB_INVALID_REGNUM, gpr_x17},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s2, x18),
+ {riscv_dwarf::dwarf_gpr_x18, riscv_dwarf::dwarf_gpr_x18,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x18},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s3, x19),
+ {riscv_dwarf::dwarf_gpr_x19, riscv_dwarf::dwarf_gpr_x19,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x19},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s4, x20),
+ {riscv_dwarf::dwarf_gpr_x20, riscv_dwarf::dwarf_gpr_x20,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x20},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s5, x21),
+ {riscv_dwarf::dwarf_gpr_x21, riscv_dwarf::dwarf_gpr_x21,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x21},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s6, x22),
+ {riscv_dwarf::dwarf_gpr_x22, riscv_dwarf::dwarf_gpr_x22,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x22},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s7, x23),
+ {riscv_dwarf::dwarf_gpr_x23, riscv_dwarf::dwarf_gpr_x23,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x23},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s8, x24),
+ {riscv_dwarf::dwarf_gpr_x24, riscv_dwarf::dwarf_gpr_x24,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x24},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s9, x25),
+ {riscv_dwarf::dwarf_gpr_x25, riscv_dwarf::dwarf_gpr_x25,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x25},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s10, x26),
+ {riscv_dwarf::dwarf_gpr_x26, riscv_dwarf::dwarf_gpr_x26,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x26},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(s11, x27),
+ {riscv_dwarf::dwarf_gpr_x27, riscv_dwarf::dwarf_gpr_x27,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x27},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(t3, x28),
+ {riscv_dwarf::dwarf_gpr_x28, riscv_dwarf::dwarf_gpr_x28,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x28},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(t4, x29),
+ {riscv_dwarf::dwarf_gpr_x29, riscv_dwarf::dwarf_gpr_x29,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x29},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(t5, x30),
+ {riscv_dwarf::dwarf_gpr_x30, riscv_dwarf::dwarf_gpr_x30,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x30},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR_ABI(t6, x31),
+ {riscv_dwarf::dwarf_gpr_x31, riscv_dwarf::dwarf_gpr_x31,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_x31},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_GPR(pc),
+ {riscv_dwarf::dwarf_gpr_pc, riscv_dwarf::dwarf_gpr_pc,
+ LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, gpr_pc},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+
+ {
+ DEFINE_FPU_ABI(ft0, f0),
+ {riscv_dwarf::dwarf_fpr_f0, riscv_dwarf::dwarf_fpr_f0,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f0},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft1, f1),
+ {riscv_dwarf::dwarf_fpr_f1, riscv_dwarf::dwarf_fpr_f1,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f1},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft2, f2),
+ {riscv_dwarf::dwarf_fpr_f2, riscv_dwarf::dwarf_fpr_f2,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f2},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft3, f3),
+ {riscv_dwarf::dwarf_fpr_f3, riscv_dwarf::dwarf_fpr_f3,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f3},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft4, f4),
+ {riscv_dwarf::dwarf_fpr_f4, riscv_dwarf::dwarf_fpr_f4,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f4},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft5, f5),
+ {riscv_dwarf::dwarf_fpr_f5, riscv_dwarf::dwarf_fpr_f5,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f5},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft6, f6),
+ {riscv_dwarf::dwarf_fpr_f6, riscv_dwarf::dwarf_fpr_f6,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f6},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft7, f7),
+ {riscv_dwarf::dwarf_fpr_f7, riscv_dwarf::dwarf_fpr_f7,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f7},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs0, f8),
+ {riscv_dwarf::dwarf_fpr_f8, riscv_dwarf::dwarf_fpr_f8,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f8},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs1, f9),
+ {riscv_dwarf::dwarf_fpr_f9, riscv_dwarf::dwarf_fpr_f9,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f9},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fa0, f10),
+ {riscv_dwarf::dwarf_fpr_f10, riscv_dwarf::dwarf_fpr_f10,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f10},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fa1, f11),
+ {riscv_dwarf::dwarf_fpr_f11, riscv_dwarf::dwarf_fpr_f11,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f11},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fa2, f12),
+ {riscv_dwarf::dwarf_fpr_f12, riscv_dwarf::dwarf_fpr_f12,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f12},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fa3, f13),
+ {riscv_dwarf::dwarf_fpr_f13, riscv_dwarf::dwarf_fpr_f13,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f13},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fa4, f14),
+ {riscv_dwarf::dwarf_fpr_f14, riscv_dwarf::dwarf_fpr_f14,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f14},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fa5, f15),
+ {riscv_dwarf::dwarf_fpr_f15, riscv_dwarf::dwarf_fpr_f15,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f15},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fa6, f16),
+ {riscv_dwarf::dwarf_fpr_f16, riscv_dwarf::dwarf_fpr_f16,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f16},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fa7, f17),
+ {riscv_dwarf::dwarf_fpr_f17, riscv_dwarf::dwarf_fpr_f17,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f17},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs2, f18),
+ {riscv_dwarf::dwarf_fpr_f18, riscv_dwarf::dwarf_fpr_f18,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f18},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs3, f19),
+ {riscv_dwarf::dwarf_fpr_f19, riscv_dwarf::dwarf_fpr_f19,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f19},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs4, f20),
+ {riscv_dwarf::dwarf_fpr_f20, riscv_dwarf::dwarf_fpr_f20,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f20},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs5, f21),
+ {riscv_dwarf::dwarf_fpr_f21, riscv_dwarf::dwarf_fpr_f21,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f21},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs6, f22),
+ {riscv_dwarf::dwarf_fpr_f22, riscv_dwarf::dwarf_fpr_f22,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f22},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs7, f23),
+ {riscv_dwarf::dwarf_fpr_f23, riscv_dwarf::dwarf_fpr_f23,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f23},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs8, f24),
+ {riscv_dwarf::dwarf_fpr_f24, riscv_dwarf::dwarf_fpr_f24,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f24},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs9, f25),
+ {riscv_dwarf::dwarf_fpr_f25, riscv_dwarf::dwarf_fpr_f25,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f25},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs10, f26),
+ {riscv_dwarf::dwarf_fpr_f26, riscv_dwarf::dwarf_fpr_f26,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f26},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(fs11, f27),
+ {riscv_dwarf::dwarf_fpr_f27, riscv_dwarf::dwarf_fpr_f27,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f27},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft8, f28),
+ {riscv_dwarf::dwarf_fpr_f28, riscv_dwarf::dwarf_fpr_f28,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f28},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft9, f29),
+ {riscv_dwarf::dwarf_fpr_f29, riscv_dwarf::dwarf_fpr_f29,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f29},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft10, f30),
+ {riscv_dwarf::dwarf_fpr_f30, riscv_dwarf::dwarf_fpr_f30,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f30},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU_ABI(ft11, f31),
+ {riscv_dwarf::dwarf_fpr_f31, riscv_dwarf::dwarf_fpr_f31,
+ LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, fpr_f31},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_FPU(fcsr),
+ {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, fpr_fcsr},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+
+ {
+ DEFINE_EXC(exception),
+ {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, exc_exception},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_EXC(fsr),
+ {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, exc_fsr},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {
+ DEFINE_EXC(far),
+ {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, exc_far},
+ nullptr,
+ nullptr,
+ nullptr,
+ },
+ {"csr",
+ nullptr,
+ 1024 * sizeof(uint32_t),
+ 0,
+ eEncodingVector,
+ eFormatVectorOfUInt32,
+ {LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM,
+ LLDB_INVALID_REGNUM, csr_bank},
+ nullptr,
+ nullptr,
+ nullptr}};
+
+static size_t k_num_register_infos = std::size(g_register_infos);
+
+RegisterContextDarwin_riscv32::RegisterContextDarwin_riscv32(
+ Thread &thread, uint32_t concrete_frame_idx)
+ : RegisterContext(thread, concrete_frame_idx), gpr(), fpr(), exc() {
+ uint32_t i;
+ for (i = 0; i < kNumErrors; i++) {
+ gpr_errs[i] = -1;
+ fpr_errs[i] = -1;
+ exc_errs[i] = -1;
+ csr_errs[i] = -1;
+ }
+}
+
+RegisterContextDarwin_riscv32::~RegisterContextDarwin_riscv32() = default;
+
+void RegisterContextDarwin_riscv32::InvalidateAllRegisters() {
+ InvalidateAllRegisterStates();
+}
+
+size_t RegisterContextDarwin_riscv32::GetRegisterCount() {
+ assert(k_num_register_infos == k_num_registers);
+ return k_num_registers;
+}
+
+const RegisterInfo *
+RegisterContextDarwin_riscv32::GetRegisterInfoAtIndex(size_t reg) {
+ assert(k_num_register_infos == k_num_registers);
+ if (reg < k_num_registers)
+ return &g_register_infos[reg];
+ return nullptr;
+}
+
+size_t RegisterContextDarwin_riscv32::GetRegisterInfosCount() {
+ return k_num_register_infos;
+}
+
+const RegisterInfo *RegisterContextDarwin_riscv32::GetRegisterInfos() {
+ return g_register_infos;
+}
+
+// General purpose registers
+static uint32_t g_gpr_regnums[] = {
+ gpr_x0, gpr_x1, gpr_x2, gpr_x3, gpr_x4, gpr_x5, gpr_x6,
+ gpr_x7, gpr_x8, gpr_x9, gpr_x10, gpr_x11, gpr_x12, gpr_x13,
+ gpr_x14, gpr_x15, gpr_x16, gpr_x17, gpr_x18, gpr_x19, gpr_x20,
+ gpr_x21, gpr_x22, gpr_x23, gpr_x24, gpr_x25, gpr_x26, gpr_x27,
+ gpr_x28, gpr_x29, gpr_x30, gpr_x31, gpr_pc};
+
+// Floating point registers
+static uint32_t g_fpr_regnums[] = {
+ fpr_f0, fpr_f1, fpr_f2, fpr_f3, fpr_f4, fpr_f5, fpr_f6,
+ fpr_f7, fpr_f8, fpr_f9, fpr_f10, fpr_f11, fpr_f12, fpr_f13,
+ fpr_f14, fpr_f15, fpr_f16, fpr_f17, fpr_f18, fpr_f19, fpr_f20,
+ fpr_f21, fpr_f22, fpr_f23, fpr_f24, fpr_f25, fpr_f26, fpr_f27,
+ fpr_f28, fpr_f29, fpr_f30, fpr_f31, fpr_fcsr};
+
+// Exception registers
+
+static uint32_t g_exc_regnums[] = {exc_exception, exc_fsr, exc_far};
+
+// CSR bank registers
+static uint32_t g_csr_regnums[] = {csr_bank};
+
+// Number of registers in each register set
+const size_t k_num_gpr_registers = std::size(g_gpr_regnums);
+const size_t k_num_fpr_registers = std::size(g_fpr_regnums);
+const size_t k_num_exc_registers = std::size(g_exc_regnums);
+const size_t k_num_csr_registers = std::size(g_csr_regnums);
+
+// Register set definitions. The first definitions at register set index of
+// zero is for all registers, followed by other registers sets. The register
+// information for the all register set need not be filled in.
+static const RegisterSet g_reg_sets[] = {
+ {
+ "General Purpose Registers",
+ "gpr",
+ k_num_gpr_registers,
+ g_gpr_regnums,
+ },
+ {"Floating Point Registers", "fpr", k_num_fpr_registers, g_fpr_regnums},
+ {"Exception State Registers", "exc", k_num_exc_registers, g_exc_regnums},
+ {"CSR register bank", "csr", k_num_csr_registers, g_csr_regnums}};
+
+const size_t k_num_regsets = std::size(g_reg_sets);
+
+size_t RegisterContextDarwin_riscv32::GetRegisterSetCount() {
+ return k_num_regsets;
+}
+
+const RegisterSet *
+RegisterContextDarwin_riscv32::GetRegisterSet(size_t reg_set) {
+ if (reg_set < k_num_regsets)
+ return &g_reg_sets[reg_set];
+ return nullptr;
+}
+
+// Register information definitions for 32 bit riscv32.
+int RegisterContextDarwin_riscv32::GetSetForNativeRegNum(int reg_num) {
+ if (reg_num < fpr_f0)
+ return GPRRegSet;
+ else if (reg_num < exc_exception)
+ return FPURegSet;
+ else if (reg_num < csr_bank)
+ return EXCRegSet;
+ else if (reg_num < k_num_registers)
+ return CSRRegSet;
+ return -1;
+}
+
+void RegisterContextDarwin_riscv32::LogGPR(Log *log, const char *title) {
+ if (log) {
+ if (title)
+ LLDB_LOGF(log, "%s", title);
+ for (uint32_t i = 0; i < k_num_gpr_registers; i++) {
+ uint32_t reg = gpr_x0 + i;
+ LLDB_LOGF(log, "%12s = 0x%4.4x", g_register_infos[reg].name,
+ (&gpr.x0)[reg]);
+ }
+ }
+}
+
+int RegisterContextDarwin_riscv32::ReadGPR(bool force) {
+ int set = GPRRegSet;
+ if (force || !RegisterSetIsCached(set)) {
+ SetError(set, Read, DoReadGPR(GetThreadID(), set, gpr));
+ }
+ return GetError(set, Read);
+}
+
+int RegisterContextDarwin_riscv32::ReadFPU(bool force) {
+ int set = FPURegSet;
+ if (force || !RegisterSetIsCached(set)) {
+ SetError(set, Read, DoReadFPU(GetThreadID(), set, fpr));
+ }
+ return GetError(set, Read);
+}
+
+int RegisterContextDarwin_riscv32::ReadEXC(bool force) {
+ int set = EXCRegSet;
+ if (force || !RegisterSetIsCached(set)) {
+ SetError(set, Read, DoReadEXC(GetThreadID(), set, exc));
+ }
+ return GetError(set, Read);
+}
+
+int RegisterContextDarwin_riscv32::ReadCSR(bool force) {
+ int set = CSRRegSet;
+ if (force || !RegisterSetIsCached(set)) {
+ SetError(set, Read, DoReadCSR(GetThreadID(), set, csr));
+ }
+ return GetError(set, Read);
+}
+
+int RegisterContextDarwin_riscv32::WriteGPR() {
+ int set = GPRRegSet;
+ if (!RegisterSetIsCached(set)) {
+ SetError(set, Write, -1);
+ return -1;
+ }
+ SetError(set, Write, DoWriteGPR(GetThreadID(), set, gpr));
+ SetError(set, Read, -1);
+ return GetError(set, Write);
+}
+
+int RegisterContextDarwin_riscv32::WriteFPU() {
+ int set = FPURegSet;
+ if (!RegisterSetIsCached(set)) {
+ SetError(set, Write, -1);
+ return -1;
+ }
+ SetError(set, Write, DoWriteFPU(GetThreadID(), set, fpr));
+ SetError(set, Read, -1);
+ return GetError(set, Write);
+}
+
+int RegisterContextDarwin_riscv32::WriteEXC() {
+ int set = EXCRegSet;
+ if (!RegisterSetIsCached(set)) {
+ SetError(set, Write, -1);
+ return -1;
+ }
+ SetError(set, Write, DoWriteEXC(GetThreadID(), set, exc));
+ SetError(set, Read, -1);
+ return GetError(set, Write);
+}
+
+int RegisterContextDarwin_riscv32::WriteCSR() {
+ int set = CSRRegSet;
+ if (!RegisterSetIsCached(set)) {
+ SetError(set, Write, -1);
+ return -1;
+ }
+ SetError(set, Write, DoWriteCSR(GetThreadID(), set, csr));
+ SetError(set, Read, -1);
+ return GetError(set, Write);
+}
+
+int RegisterContextDarwin_riscv32::ReadRegisterSet(uint32_t set, bool force) {
+ switch (set) {
+ case GPRRegSet:
+ return ReadGPR(force);
+ case FPURegSet:
+ return ReadFPU(force);
+ case EXCRegSet:
+ return ReadEXC(force);
+ case CSRRegSet:
+ return ReadCSR(force);
+ default:
+ break;
+ }
+ return -1;
+}
+
+int RegisterContextDarwin_riscv32::WriteRegisterSet(uint32_t set) {
+ // Make sure we have a valid context to set.
+ if (RegisterSetIsCached(set)) {
+ switch (set) {
+ case GPRRegSet:
+ return WriteGPR();
+ case FPURegSet:
+ return WriteFPU();
+ case EXCRegSet:
+ return WriteEXC();
+ case CSRRegSet:
+ return WriteCSR();
+ default:
+ break;
+ }
+ }
+ return -1;
+}
+
+bool RegisterContextDarwin_riscv32::ReadRegister(const RegisterInfo *reg_info,
+ RegisterValue &value) {
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ int set = RegisterContextDarwin_riscv32::GetSetForNativeRegNum(reg);
+
+ if (set == -1)
+ return false;
+
+ if (ReadRegisterSet(set, false) != 0)
+ return false;
+
+ switch (reg) {
+ case gpr_x0:
+ case gpr_x1:
+ case gpr_x2:
+ case gpr_x3:
+ case gpr_x4:
+ case gpr_x5:
+ case gpr_x6:
+ case gpr_x7:
+ case gpr_x8:
+ case gpr_x9:
+ case gpr_x10:
+ case gpr_x11:
+ case gpr_x12:
+ case gpr_x13:
+ case gpr_x14:
+ case gpr_x15:
+ case gpr_x16:
+ case gpr_x17:
+ case gpr_x18:
+ case gpr_x19:
+ case gpr_x20:
+ case gpr_x21:
+ case gpr_x22:
+ case gpr_x23:
+ case gpr_x24:
+ case gpr_x25:
+ case gpr_x26:
+ case gpr_x27:
+ case gpr_x28:
+ case gpr_x29:
+ case gpr_x30:
+ case gpr_x31:
+ case gpr_pc:
+ value = (&gpr.x0)[reg - gpr_x0];
+ break;
+
+ case fpr_f0:
+ case fpr_f1:
+ case fpr_f2:
+ case fpr_f3:
+ case fpr_f4:
+ case fpr_f5:
+ case fpr_f6:
+ case fpr_f7:
+ case fpr_f8:
+ case fpr_f9:
+ case fpr_f10:
+ case fpr_f11:
+ case fpr_f12:
+ case fpr_f13:
+ case fpr_f14:
+ case fpr_f15:
+ case fpr_f16:
+ case fpr_f17:
+ case fpr_f18:
+ case fpr_f19:
+ case fpr_f20:
+ case fpr_f21:
+ case fpr_f22:
+ case fpr_f23:
+ case fpr_f24:
+ case fpr_f25:
+ case fpr_f26:
+ case fpr_f27:
+ case fpr_f28:
+ case fpr_f29:
+ case fpr_f30:
+ case fpr_f31:
+ case fpr_fcsr:
+ value = (&fpr.f0)[reg - fpr_f0];
+ break;
+
+ case exc_exception:
+ value = exc.exception;
+ break;
+
+ case exc_fsr:
+ value = exc.fsr;
+ break;
+
+ case exc_far:
+ value = exc.far;
+ break;
+
+ case csr_bank:
+ // These values don't fit into scalar types,
+ // RegisterContext::ReadRegisterBytes() must be used for these registers
+ //::memcpy (reg_value.value.vector.uint8, fpu.stmm[reg - fpu_stmm0].bytes,
+ // 10);
+
+ // AArch64 copies NEON registers with
+ // value.SetBytes(csr.bytes, reg_info->byte_size,
+ // endian::InlHostByteOrder());
+ return false;
+
+ default:
+ return false;
+ }
+ return true;
+}
+
+bool RegisterContextDarwin_riscv32::WriteRegister(const RegisterInfo *reg_info,
+ const RegisterValue &value) {
+ const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+ int set = GetSetForNativeRegNum(reg);
+
+ if (set == -1)
+ return false;
+
+ if (ReadRegisterSet(set, false) != 0)
+ return false;
+
+ switch (reg) {
+ case gpr_x0:
+ case gpr_x1:
+ case gpr_x2:
+ case gpr_x3:
+ case gpr_x4:
+ case gpr_x5:
+ case gpr_x6:
+ case gpr_x7:
+ case gpr_x8:
+ case gpr_x9:
+ case gpr_x10:
+ case gpr_x11:
+ case gpr_x12:
+ case gpr_x13:
+ case gpr_x14:
+ case gpr_x15:
+ case gpr_x16:
+ case gpr_x17:
+ case gpr_x18:
+ case gpr_x19:
+ case gpr_x20:
+ case gpr_x21:
+ case gpr_x22:
+ case gpr_x23:
+ case gpr_x24:
+ case gpr_x25:
+ case gpr_x26:
+ case gpr_x27:
+ case gpr_x28:
+ case gpr_x29:
+ case gpr_x30:
+ case gpr_x31:
+ case gpr_pc:
+ (&gpr.x0)[reg - gpr_x0] = value.GetAsUInt32();
+ break;
+
+ case fpr_f0:
+ case fpr_f1:
+ case fpr_f2:
+ case fpr_f3:
+ case fpr_f4:
+ case fpr_f5:
+ case fpr_f6:
+ case fpr_f7:
+ case fpr_f8:
+ case fpr_f9:
+ case fpr_f10:
+ case fpr_f11:
+ case fpr_f12:
+ case fpr_f13:
+ case fpr_f14:
+ case fpr_f15:
+ case fpr_f16:
+ case fpr_f17:
+ case fpr_f18:
+ case fpr_f19:
+ case fpr_f20:
+ case fpr_f21:
+ case fpr_f22:
+ case fpr_f23:
+ case fpr_f24:
+ case fpr_f25:
+ case fpr_f26:
+ case fpr_f27:
+ case fpr_f28:
+ case fpr_f29:
+ case fpr_f30:
+ case fpr_f31:
+ case fpr_fcsr:
+ (&fpr.f0)[reg - fpr_f0] = value.GetAsUInt32();
+ break;
+
+ case exc_exception:
+ exc.exception = value.GetAsUInt32();
+ break;
+
+ case exc_fsr:
+ exc.fsr = value.GetAsUInt32();
+ break;
+
+ case exc_far:
+ exc.far = value.GetAsUInt32();
+ break;
+
+ case csr_bank:
+ // These values don't fit into scalar types,
+ // RegisterContext::ReadRegisterBytes() must be used for these registers
+ //::memcpy(csr.bytes, value.GetBytes(),
+ // value.GetByteSize());
+ return false;
+
+ default:
+ return false;
+ }
+ return WriteRegisterSet(set) == 0;
+}
+
+bool RegisterContextDarwin_riscv32::ReadAllRegisterValues(
+ lldb::WritableDataBufferSP &data_sp) {
+ data_sp = std::make_shared<DataBufferHeap>(REG_CONTEXT_SIZE, 0);
+ if (ReadGPR(false) == 0 && ReadFPU(false) == 0 && ReadEXC(false) == 0 &&
+ ReadCSR(false) == 0) {
+ uint8_t *dst = data_sp->GetBytes();
+ ::memcpy(dst, &gpr, sizeof(gpr));
+ dst += sizeof(gpr);
+
+ ::memcpy(dst, &fpr, sizeof(fpr));
+ dst += sizeof(gpr);
+
+ ::memcpy(dst, &exc, sizeof(exc));
+ return true;
+
+ ::memcpy(dst, &csr, sizeof(csr));
+ return true;
+ }
+ return false;
+}
+
+bool RegisterContextDarwin_riscv32::WriteAllRegisterValues(
+ const lldb::DataBufferSP &data_sp) {
+ if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
+ const uint8_t *src = data_sp->GetBytes();
+ ::memcpy(&gpr, src, sizeof(gpr));
+ src += sizeof(gpr);
+
+ ::memcpy(&fpr, src, sizeof(fpr));
+ src += sizeof(fpr);
+
+ ::memcpy(&exc, src, sizeof(exc));
+ src += sizeof(exc);
+
+ ::memcpy(&csr, src, sizeof(csr));
+ uint32_t success_count = 0;
+
+ if (WriteGPR() == 0)
+ ++success_count;
+ if (WriteFPU() == 0)
+ ++success_count;
+ if (WriteEXC() == 0)
+ ++success_count;
+ if (WriteCSR() == 0)
+ ++success_count;
+ return success_count == 3;
+ }
+ return false;
+}
+
+uint32_t RegisterContextDarwin_riscv32::ConvertRegisterKindToRegisterNumber(
+ lldb::RegisterKind kind, uint32_t reg) {
+ if (kind == eRegisterKindGeneric) {
+ switch (reg) {
+ case LLDB_REGNUM_GENERIC_PC:
+ return gpr_pc;
+ case LLDB_REGNUM_GENERIC_SP:
+ return gpr_x2;
+ case LLDB_REGNUM_GENERIC_FP:
+ return gpr_x8;
+ case LLDB_REGNUM_GENERIC_RA:
+ return gpr_x1;
+ default:
+ break;
+ }
+ } else if (kind == eRegisterKindEHFrame || kind == eRegisterKindDWARF) {
+ switch (reg) {
+ case riscv_dwarf::dwarf_gpr_x0:
+ case riscv_dwarf::dwarf_gpr_x1:
+ case riscv_dwarf::dwarf_gpr_x2:
+ case riscv_dwarf::dwarf_gpr_x3:
+ case riscv_dwarf::dwarf_gpr_x4:
+ case riscv_dwarf::dwarf_gpr_x5:
+ case riscv_dwarf::dwarf_gpr_x6:
+ case riscv_dwarf::dwarf_gpr_x7:
+ case riscv_dwarf::dwarf_gpr_x8:
+ case riscv_dwarf::dwarf_gpr_x9:
+ case riscv_dwarf::dwarf_gpr_x10:
+ case riscv_dwarf::dwarf_gpr_x11:
+ case riscv_dwarf::dwarf_gpr_x12:
+ case riscv_dwarf::dwarf_gpr_x13:
+ case riscv_dwarf::dwarf_gpr_x14:
+ case riscv_dwarf::dwarf_gpr_x15:
+ case riscv_dwarf::dwarf_gpr_x16:
+ case riscv_dwarf::dwarf_gpr_x17:
+ case riscv_dwarf::dwarf_gpr_x18:
+ case riscv_dwarf::dwarf_gpr_x19:
+ case riscv_dwarf::dwarf_gpr_x20:
+ case riscv_dwarf::dwarf_gpr_x21:
+ case riscv_dwarf::dwarf_gpr_x22:
+ case riscv_dwarf::dwarf_gpr_x23:
+ case riscv_dwarf::dwarf_gpr_x24:
+ case riscv_dwarf::dwarf_gpr_x25:
+ case riscv_dwarf::dwarf_gpr_x26:
+ case riscv_dwarf::dwarf_gpr_x27:
+ case riscv_dwarf::dwarf_gpr_x28:
+ case riscv_dwarf::dwarf_gpr_x29:
+ case riscv_dwarf::dwarf_gpr_x30:
+ case riscv_dwarf::dwarf_gpr_x31:
+ return gpr_x0 + (reg - riscv_dwarf::dwarf_gpr_x0);
+
+ case riscv_dwarf::dwarf_fpr_f0:
+ case riscv_dwarf::dwarf_fpr_f1:
+ case riscv_dwarf::dwarf_fpr_f2:
+ case riscv_dwarf::dwarf_fpr_f3:
+ case riscv_dwarf::dwarf_fpr_f4:
+ case riscv_dwarf::dwarf_fpr_f5:
+ case riscv_dwarf::dwarf_fpr_f6:
+ case riscv_dwarf::dwarf_fpr_f7:
+ case riscv_dwarf::dwarf_fpr_f8:
+ case riscv_dwarf::dwarf_fpr_f9:
+ case riscv_dwarf::dwarf_fpr_f10:
+ case riscv_dwarf::dwarf_fpr_f11:
+ case riscv_dwarf::dwarf_fpr_f12:
+ case riscv_dwarf::dwarf_fpr_f13:
+ case riscv_dwarf::dwarf_fpr_f14:
+ case riscv_dwarf::dwarf_fpr_f15:
+ case riscv_dwarf::dwarf_fpr_f16:
+ case riscv_dwarf::dwarf_fpr_f17:
+ case riscv_dwarf::dwarf_fpr_f18:
+ case riscv_dwarf::dwarf_fpr_f19:
+ case riscv_dwarf::dwarf_fpr_f20:
+ case riscv_dwarf::dwarf_fpr_f21:
+ case riscv_dwarf::dwarf_fpr_f22:
+ case riscv_dwarf::dwarf_fpr_f23:
+ case riscv_dwarf::dwarf_fpr_f24:
+ case riscv_dwarf::dwarf_fpr_f25:
+ case riscv_dwarf::dwarf_fpr_f26:
+ case riscv_dwarf::dwarf_fpr_f27:
+ case riscv_dwarf::dwarf_fpr_f28:
+ case riscv_dwarf::dwarf_fpr_f29:
+ case riscv_dwarf::dwarf_fpr_f30:
+ case riscv_dwarf::dwarf_fpr_f31:
+ return fpr_f0 + (reg - riscv_dwarf::dwarf_fpr_f0);
+
+ default:
+ break;
+ }
+ } else if (kind == eRegisterKindLLDB) {
+ return reg;
+ }
+ return LLDB_INVALID_REGNUM;
+}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_riscv32.h b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_riscv32.h
new file mode 100644
index 0000000000000..22d61aef712a6
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextDarwin_riscv32.h
@@ -0,0 +1,260 @@
+//===-- RegisterContextDarwin_riscv32.h -------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_RISCV32_H
+#define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_RISCV32_H
+
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/lldb-private.h"
+
+class RegisterContextDarwin_riscv32 : public lldb_private::RegisterContext {
+public:
+ RegisterContextDarwin_riscv32(lldb_private::Thread &thread,
+ uint32_t concrete_frame_idx);
+
+ ~RegisterContextDarwin_riscv32() override;
+
+ void InvalidateAllRegisters() override;
+
+ size_t GetRegisterCount() override;
+
+ const lldb_private::RegisterInfo *GetRegisterInfoAtIndex(size_t reg) override;
+
+ size_t GetRegisterSetCount() override;
+
+ const lldb_private::RegisterSet *GetRegisterSet(size_t set) override;
+
+ bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
+ lldb_private::RegisterValue &value) override;
+
+ bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
+ const lldb_private::RegisterValue &value) override;
+
+ bool ReadAllRegisterValues(lldb::WritableDataBufferSP &data_sp) override;
+
+ bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+ uint32_t ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+ uint32_t num) override;
+
+ struct GPR {
+ uint32_t x0;
+ uint32_t x1;
+ uint32_t x2;
+ uint32_t x3;
+ uint32_t x4;
+ uint32_t x5;
+ uint32_t x6;
+ uint32_t x7;
+ uint32_t x8;
+ uint32_t x9;
+ uint32_t x10;
+ uint32_t x11;
+ uint32_t x12;
+ uint32_t x13;
+ uint32_t x14;
+ uint32_t x15;
+ uint32_t x16;
+ uint32_t x17;
+ uint32_t x18;
+ uint32_t x19;
+ uint32_t x20;
+ uint32_t x21;
+ uint32_t x22;
+ uint32_t x23;
+ uint32_t x24;
+ uint32_t x25;
+ uint32_t x26;
+ uint32_t x27;
+ uint32_t x28;
+ uint32_t x29;
+ uint32_t x30;
+ uint32_t x31;
+ uint32_t pc;
+ };
+
+ struct FPU {
+ uint32_t f0;
+ uint32_t f1;
+ uint32_t f2;
+ uint32_t f3;
+ uint32_t f4;
+ uint32_t f5;
+ uint32_t f6;
+ uint32_t f7;
+ uint32_t f8;
+ uint32_t f9;
+ uint32_t f10;
+ uint32_t f11;
+ uint32_t f12;
+ uint32_t f13;
+ uint32_t f14;
+ uint32_t f15;
+ uint32_t f16;
+ uint32_t f17;
+ uint32_t f18;
+ uint32_t f19;
+ uint32_t f20;
+ uint32_t f21;
+ uint32_t f22;
+ uint32_t f23;
+ uint32_t f24;
+ uint32_t f25;
+ uint32_t f26;
+ uint32_t f27;
+ uint32_t f28;
+ uint32_t f29;
+ uint32_t f30;
+ uint32_t f31;
+ uint32_t fcsr;
+ };
+
+ struct EXC {
+ uint32_t exception;
+ uint32_t fsr;
+ uint32_t far;
+ };
+
+ struct CSR {
+ uint32_t csr[1024];
+ };
+
+protected:
+ enum {
+ GPRRegSet = 2, // RV32_THREAD_STATE
+ EXCRegSet = 3, // RV32_EXCEPTION_STATE
+ FPURegSet = 4, // RV_FP32_STATE
+ CSRRegSet1 = 6, // RV_CSR_STATE1
+ CSRRegSet2 = 7, // RV_CSR_STATE2
+ CSRRegSet3 = 8, // RV_CSR_STATE3
+ CSRRegSet4 = 9, // RV_CSR_STATE4
+ CSRRegSet = 10 // full 16kbyte CSR reg bank
+ };
+
+ enum {
+ GPRWordCount = sizeof(GPR) / sizeof(uint32_t),
+ FPUWordCount = sizeof(FPU) / sizeof(uint32_t),
+ EXCWordCount = sizeof(EXC) / sizeof(uint32_t),
+ CSRWordCount = sizeof(CSR) / sizeof(uint32_t)
+ };
+
+ enum { Read = 0, Write = 1, kNumErrors = 2 };
+
+ GPR gpr;
+ FPU fpr;
+ EXC exc;
+ CSR csr;
+ int gpr_errs[2]; // Read/Write errors
+ int fpr_errs[2]; // Read/Write errors
+ int exc_errs[2]; // Read/Write errors
+ int csr_errs[2]; // Read/Write errors
+
+ void InvalidateAllRegisterStates() {
+ SetError(GPRRegSet, Read, -1);
+ SetError(FPURegSet, Read, -1);
+ SetError(EXCRegSet, Read, -1);
+ SetError(CSRRegSet, Read, -1);
+ }
+
+ int GetError(int flavor, uint32_t err_idx) const {
+ if (err_idx < kNumErrors) {
+ switch (flavor) {
+ // When getting all errors, just OR all values together to see if
+ // we got any kind of error.
+ case GPRRegSet:
+ return gpr_errs[err_idx];
+ case FPURegSet:
+ return fpr_errs[err_idx];
+ case EXCRegSet:
+ return exc_errs[err_idx];
+ case CSRRegSet:
+ return csr_errs[err_idx];
+ default:
+ break;
+ }
+ }
+ return -1;
+ }
+
+ bool SetError(int flavor, uint32_t err_idx, int err) {
+ if (err_idx < kNumErrors) {
+ switch (flavor) {
+ case GPRRegSet:
+ gpr_errs[err_idx] = err;
+ return true;
+
+ case FPURegSet:
+ fpr_errs[err_idx] = err;
+ return true;
+
+ case EXCRegSet:
+ exc_errs[err_idx] = err;
+ return true;
+
+ case CSRRegSet:
+ csr_errs[err_idx] = err;
+ return true;
+
+ default:
+ break;
+ }
+ }
+ return false;
+ }
+
+ bool RegisterSetIsCached(int set) const { return GetError(set, Read) == 0; }
+
+ void LogGPR(lldb_private::Log *log, const char *title);
+
+ int ReadGPR(bool force);
+
+ int ReadFPU(bool force);
+
+ int ReadEXC(bool force);
+
+ int ReadCSR(bool force);
+
+ int WriteGPR();
+
+ int WriteFPU();
+
+ int WriteEXC();
+
+ int WriteCSR();
+
+ // Subclasses override these to do the actual reading.
+ virtual int DoReadGPR(lldb::tid_t tid, int flavor, GPR &gpr) = 0;
+
+ virtual int DoReadFPU(lldb::tid_t tid, int flavor, FPU &fpr) = 0;
+
+ virtual int DoReadEXC(lldb::tid_t tid, int flavor, EXC &exc) = 0;
+
+ virtual int DoReadCSR(lldb::tid_t tid, int flavor, CSR &exc) = 0;
+
+ virtual int DoWriteGPR(lldb::tid_t tid, int flavor, const GPR &gpr) = 0;
+
+ virtual int DoWriteFPU(lldb::tid_t tid, int flavor, const FPU &fpr) = 0;
+
+ virtual int DoWriteEXC(lldb::tid_t tid, int flavor, const EXC &exc) = 0;
+
+ virtual int DoWriteCSR(lldb::tid_t tid, int flavor, const CSR &exc) = 0;
+
+ int ReadRegisterSet(uint32_t set, bool force);
+
+ int WriteRegisterSet(uint32_t set);
+
+ static uint32_t GetRegisterNumber(uint32_t reg_kind, uint32_t reg_num);
+
+ static int GetSetForNativeRegNum(int reg_num);
+
+ static size_t GetRegisterInfosCount();
+
+ static const lldb_private::RegisterInfo *GetRegisterInfos();
+};
+
+#endif // LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXTDARWIN_RISCV32_H
diff --git a/lldb/test/API/macosx/riscv32-corefile/Makefile b/lldb/test/API/macosx/riscv32-corefile/Makefile
new file mode 100644
index 0000000000000..04f268758d00c
--- /dev/null
+++ b/lldb/test/API/macosx/riscv32-corefile/Makefile
@@ -0,0 +1,7 @@
+MAKE_DSYM := NO
+CXX_SOURCES := create-empty-riscv-corefile.cpp
+EXE := create-empty-riscv-corefile
+
+all: create-empty-riscv-corefile
+
+include Makefile.rules
diff --git a/lldb/test/API/macosx/riscv32-corefile/TestRV32MachOCorefile.py b/lldb/test/API/macosx/riscv32-corefile/TestRV32MachOCorefile.py
new file mode 100644
index 0000000000000..8d11821d38985
--- /dev/null
+++ b/lldb/test/API/macosx/riscv32-corefile/TestRV32MachOCorefile.py
@@ -0,0 +1,82 @@
+"""Test that all of the GPR registers are read correctly from a riscv32 corefile."""
+
+import os
+import re
+import subprocess
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class TestRV32MachOCorefile(TestBase):
+ NO_DEBUG_INFO_TESTCASE = True
+
+ @skipUnlessDarwin
+ def test_riscv32_gpr_corefile_registers(self):
+ self.build()
+ create_corefile = self.getBuildArtifact("create-empty-riscv-corefile")
+ corefile = self.getBuildArtifact("core")
+ call(create_corefile + " " + corefile, shell=True)
+
+ target = self.dbg.CreateTarget("")
+ process = target.LoadCore(corefile)
+
+ process = target.GetProcess()
+ self.assertEqual(process.GetNumThreads(), 1)
+
+ thread = process.GetThreadAtIndex(0)
+ self.assertEqual(thread.GetNumFrames(), 1)
+
+ frame = thread.GetFrameAtIndex(0)
+ gpr_regs = frame.registers.GetValueAtIndex(0)
+
+ self.assertEqual(gpr_regs.GetName(), "General Purpose Registers")
+ self.assertEqual(gpr_regs.GetNumChildren(), 33)
+ regnames = [
+ "zero",
+ "ra",
+ "sp",
+ "gp",
+ "tp",
+ "t0",
+ "t1",
+ "t2",
+ "fp",
+ "s1",
+ "a0",
+ "a1",
+ "a2",
+ "a3",
+ "a4",
+ "a5",
+ "a6",
+ "a7",
+ "s2",
+ "s3",
+ "s4",
+ "s5",
+ "s6",
+ "s7",
+ "s8",
+ "s9",
+ "s10",
+ "s11",
+ "t3",
+ "t4",
+ "t5",
+ "t6",
+ "pc",
+ ]
+
+ idx = 0
+ while idx < len(regnames):
+ self.assertEqual(gpr_regs.GetChildAtIndex(idx).GetName(), regnames[idx])
+ idx = idx + 1
+
+ idx = 0
+ while idx < len(regnames):
+ val = idx | (idx << 8) | (idx << 16) | (idx << 24)
+ self.assertEqual(gpr_regs.GetChildAtIndex(idx).GetValueAsUnsigned(), val)
+ idx = idx + 1
diff --git a/lldb/test/API/macosx/riscv32-corefile/create-empty-riscv-corefile.cpp b/lldb/test/API/macosx/riscv32-corefile/create-empty-riscv-corefile.cpp
new file mode 100644
index 0000000000000..907cca3b70b41
--- /dev/null
+++ b/lldb/test/API/macosx/riscv32-corefile/create-empty-riscv-corefile.cpp
@@ -0,0 +1,116 @@
+#include <inttypes.h>
+#include <mach-o/loader.h>
+#include <mach/thread_status.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <string>
+#include <sys/errno.h>
+#include <uuid/uuid.h>
+#include <vector>
+
+#define CPU_TYPE_RISCV 24
+#define CPU_SUBTYPE_RISCV_ALL 0
+#define RV32_THREAD_STATE 2
+// x0-x31 + pc, all 32-bit
+#define RV32_THREAD_STATE_COUNT 33
+
+union uint32_buf {
+ uint8_t bytebuf[4];
+ uint32_t val;
+};
+
+union uint64_buf {
+ uint8_t bytebuf[8];
+ uint64_t val;
+};
+
+void add_uint64(std::vector<uint8_t> &buf, uint64_t val) {
+ uint64_buf conv;
+ conv.val = val;
+ for (int i = 0; i < 8; i++)
+ buf.push_back(conv.bytebuf[i]);
+}
+
+void add_uint32(std::vector<uint8_t> &buf, uint32_t val) {
+ uint32_buf conv;
+ conv.val = val;
+ for (int i = 0; i < 4; i++)
+ buf.push_back(conv.bytebuf[i]);
+}
+
+std::vector<uint8_t> lc_thread_load_command() {
+ std::vector<uint8_t> data;
+ add_uint32(data, LC_THREAD); // thread_command.cmd
+ add_uint32(data, 4 + 4 + 4 + 4 +
+ (RV32_THREAD_STATE_COUNT * 4)); // thread_command.cmdsize
+ add_uint32(data, RV32_THREAD_STATE); // thread_command.flavor
+ add_uint32(data, RV32_THREAD_STATE_COUNT); // thread_command.count
+ for (int i = 0; i < RV32_THREAD_STATE_COUNT; i++) {
+ add_uint32(data, i | (i << 8) | (i << 16) | (i << 24));
+ }
+ return data;
+}
+
+int main(int argc, char **argv) {
+ if (argc != 2) {
+ fprintf(stderr,
+ "usage: create-empty-riscv-corefile output-corefile-name\n");
+ exit(1);
+ }
+
+ cpu_type_t cputype = CPU_TYPE_RISCV;
+ cpu_subtype_t cpusubtype = CPU_SUBTYPE_RISCV_ALL;
+
+ // An array of load commands (in the form of byte arrays)
+ std::vector<std::vector<uint8_t>> load_commands;
+
+ // An array of corefile contents (page data, lc_note data, etc)
+ std::vector<uint8_t> payload;
+
+ // First add all the load commands / payload so we can figure out how large
+ // the load commands will actually be.
+ load_commands.push_back(lc_thread_load_command());
+
+ int size_of_load_commands = 0;
+ for (const auto &lc : load_commands)
+ size_of_load_commands += lc.size();
+
+ int header_and_load_cmd_room =
+ sizeof(struct mach_header_64) + size_of_load_commands;
+
+ // Erase the load commands / payload now that we know how much space is
+ // needed, redo it.
+ load_commands.clear();
+ payload.clear();
+
+ load_commands.push_back(lc_thread_load_command());
+
+ struct mach_header mh;
+ mh.magic = MH_MAGIC;
+ mh.cputype = cputype;
+
+ mh.cpusubtype = cpusubtype;
+ mh.filetype = MH_CORE;
+ mh.ncmds = load_commands.size();
+ mh.sizeofcmds = size_of_load_commands;
+ mh.flags = 0;
+
+ FILE *f = fopen(argv[1], "w");
+
+ if (f == nullptr) {
+ fprintf(stderr, "Unable to open file %s for writing\n", argv[1]);
+ exit(1);
+ }
+
+ fwrite(&mh, sizeof(struct mach_header), 1, f);
+
+ for (const auto &lc : load_commands)
+ fwrite(lc.data(), lc.size(), 1, f);
+
+ fseek(f, header_and_load_cmd_room, SEEK_SET);
+
+ fwrite(payload.data(), payload.size(), 1, f);
+
+ fclose(f);
+}
More information about the lldb-commits
mailing list