Skip to content

Commit d3a9043

Browse files
[lldb][RISCV] Add RegisterContextPOSIXCore for RISC-V 64 (#93297)
The PR adds the support of CoreDump debugging for RISC-V 64. It implements new `RegisterContextCorePOSIX_riscv64` class. Also, the contribution fixes `GetRegisterCount()` -> `GetRegisterSetCount()` misprint in `RegisterContextPOSIX_riscv64::GetRegisterSetCount()` method, which leaded to `set && "Register set should be valid."` assertion during `register info aX` command call. The patch was tested (on coredumps generated for simple Integer/FP calculation code) for _cross x86_64 -> RISCV_ and _native RISCV_ LLDB builds. There were performed basic LLDB functionality tests, such as: - CoreDump file load - Backtrace / frames - GP/FP registers read/info/list - Basic switch between threads - Disassembler code - Memory regions read / display
1 parent 8ab578a commit d3a9043

File tree

8 files changed

+251
-2
lines changed

8 files changed

+251
-2
lines changed

lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_riscv64.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ RegisterContextPOSIX_riscv64::GetRegisterInfoAtIndex(size_t reg) {
5858
}
5959

6060
size_t RegisterContextPOSIX_riscv64::GetRegisterSetCount() {
61-
return m_register_info_up->GetRegisterCount();
61+
return m_register_info_up->GetRegisterSetCount();
6262
}
6363

6464
const lldb_private::RegisterSet *

lldb/source/Plugins/Process/elf-core/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ add_lldb_library(lldbPluginProcessElfCore PLUGIN
99
RegisterContextPOSIXCore_ppc64le.cpp
1010
RegisterContextPOSIXCore_s390x.cpp
1111
RegisterContextPOSIXCore_x86_64.cpp
12+
RegisterContextPOSIXCore_riscv64.cpp
1213
RegisterUtilities.cpp
1314

1415
LINK_LIBS
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
//===-- RegisterContextPOSIXCore_riscv64.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+
9+
#include "RegisterContextPOSIXCore_riscv64.h"
10+
11+
#include "lldb/Utility/DataBufferHeap.h"
12+
13+
using namespace lldb_private;
14+
15+
std::unique_ptr<RegisterContextCorePOSIX_riscv64>
16+
RegisterContextCorePOSIX_riscv64::Create(Thread &thread, const ArchSpec &arch,
17+
const DataExtractor &gpregset,
18+
llvm::ArrayRef<CoreNote> notes) {
19+
return std::unique_ptr<RegisterContextCorePOSIX_riscv64>(
20+
new RegisterContextCorePOSIX_riscv64(
21+
thread, std::make_unique<RegisterInfoPOSIX_riscv64>(arch, Flags()),
22+
gpregset, notes));
23+
}
24+
25+
RegisterContextCorePOSIX_riscv64::RegisterContextCorePOSIX_riscv64(
26+
Thread &thread, std::unique_ptr<RegisterInfoPOSIX_riscv64> register_info,
27+
const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
28+
: RegisterContextPOSIX_riscv64(thread, std::move(register_info)) {
29+
30+
m_gpr_buffer = std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
31+
gpregset.GetByteSize());
32+
m_gpr.SetData(m_gpr_buffer);
33+
m_gpr.SetByteOrder(gpregset.GetByteOrder());
34+
35+
ArchSpec arch = m_register_info_up->GetTargetArchitecture();
36+
DataExtractor fpregset = getRegset(notes, arch.GetTriple(), FPR_Desc);
37+
m_fpr_buffer = std::make_shared<DataBufferHeap>(fpregset.GetDataStart(),
38+
fpregset.GetByteSize());
39+
m_fpr.SetData(m_fpr_buffer);
40+
m_fpr.SetByteOrder(fpregset.GetByteOrder());
41+
}
42+
43+
RegisterContextCorePOSIX_riscv64::~RegisterContextCorePOSIX_riscv64() = default;
44+
45+
bool RegisterContextCorePOSIX_riscv64::ReadGPR() { return true; }
46+
47+
bool RegisterContextCorePOSIX_riscv64::ReadFPR() { return true; }
48+
49+
bool RegisterContextCorePOSIX_riscv64::WriteGPR() {
50+
assert(false && "Writing registers is not allowed for core dumps");
51+
return false;
52+
}
53+
54+
bool RegisterContextCorePOSIX_riscv64::WriteFPR() {
55+
assert(false && "Writing registers is not allowed for core dumps");
56+
return false;
57+
}
58+
59+
bool RegisterContextCorePOSIX_riscv64::ReadRegister(
60+
const RegisterInfo *reg_info, RegisterValue &value) {
61+
const uint8_t *src = nullptr;
62+
lldb::offset_t offset = reg_info->byte_offset;
63+
64+
if (IsGPR(reg_info->kinds[lldb::eRegisterKindLLDB])) {
65+
src = m_gpr.GetDataStart();
66+
} else if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) {
67+
src = m_fpr.GetDataStart();
68+
offset -= GetGPRSize();
69+
} else {
70+
return false;
71+
}
72+
73+
Status error;
74+
value.SetFromMemoryData(*reg_info, src + offset, reg_info->byte_size,
75+
lldb::eByteOrderLittle, error);
76+
return error.Success();
77+
}
78+
79+
bool RegisterContextCorePOSIX_riscv64::WriteRegister(
80+
const RegisterInfo *reg_info, const RegisterValue &value) {
81+
return false;
82+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
//===-- RegisterContextPOSIXCore_riscv64.h ----------------------*- C++ -*-===//
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+
9+
#ifndef LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_RISCV64_H
10+
#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_RISCV64_H
11+
12+
#include "Plugins/Process/Utility/RegisterContextPOSIX_riscv64.h"
13+
#include "Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.h"
14+
15+
#include "Plugins/Process/elf-core/RegisterUtilities.h"
16+
#include "lldb/Target/Thread.h"
17+
#include "lldb/Utility/DataExtractor.h"
18+
#include "lldb/Utility/RegisterValue.h"
19+
20+
#include <memory>
21+
22+
class RegisterContextCorePOSIX_riscv64 : public RegisterContextPOSIX_riscv64 {
23+
public:
24+
static std::unique_ptr<RegisterContextCorePOSIX_riscv64>
25+
Create(lldb_private::Thread &thread, const lldb_private::ArchSpec &arch,
26+
const lldb_private::DataExtractor &gpregset,
27+
llvm::ArrayRef<lldb_private::CoreNote> notes);
28+
29+
~RegisterContextCorePOSIX_riscv64() override;
30+
31+
bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
32+
lldb_private::RegisterValue &value) override;
33+
34+
bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
35+
const lldb_private::RegisterValue &value) override;
36+
37+
protected:
38+
RegisterContextCorePOSIX_riscv64(
39+
lldb_private::Thread &thread,
40+
std::unique_ptr<RegisterInfoPOSIX_riscv64> register_info,
41+
const lldb_private::DataExtractor &gpregset,
42+
llvm::ArrayRef<lldb_private::CoreNote> notes);
43+
44+
bool ReadGPR() override;
45+
46+
bool ReadFPR() override;
47+
48+
bool WriteGPR() override;
49+
50+
bool WriteFPR() override;
51+
52+
private:
53+
lldb::DataBufferSP m_gpr_buffer;
54+
lldb::DataBufferSP m_fpr_buffer;
55+
56+
lldb_private::DataExtractor m_gpr;
57+
lldb_private::DataExtractor m_fpr;
58+
};
59+
60+
#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_RISCV64_H

lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "RegisterContextPOSIXCore_mips64.h"
3636
#include "RegisterContextPOSIXCore_powerpc.h"
3737
#include "RegisterContextPOSIXCore_ppc64le.h"
38+
#include "RegisterContextPOSIXCore_riscv64.h"
3839
#include "RegisterContextPOSIXCore_s390x.h"
3940
#include "RegisterContextPOSIXCore_x86_64.h"
4041
#include "ThreadElfCore.h"
@@ -168,7 +169,8 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
168169
}
169170

170171
if (!reg_interface && arch.GetMachine() != llvm::Triple::aarch64 &&
171-
arch.GetMachine() != llvm::Triple::arm) {
172+
arch.GetMachine() != llvm::Triple::arm &&
173+
arch.GetMachine() != llvm::Triple::riscv64) {
172174
LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
173175
__FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
174176
assert(false && "Architecture or OS not supported");
@@ -184,6 +186,10 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
184186
*this, std::make_unique<RegisterInfoPOSIX_arm>(arch), m_gpregset_data,
185187
m_notes);
186188
break;
189+
case llvm::Triple::riscv64:
190+
m_thread_reg_ctx_sp = RegisterContextCorePOSIX_riscv64::Create(
191+
*this, arch, m_gpregset_data, m_notes);
192+
break;
187193
case llvm::Triple::mipsel:
188194
case llvm::Triple::mips:
189195
m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(

lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,14 @@ class LinuxCoreTestCase(TestBase):
2121
_x86_64_pid = 32259
2222
_s390x_pid = 1045
2323
_ppc64le_pid = 28147
24+
_riscv64_pid = 89328
2425

2526
_aarch64_regions = 4
2627
_i386_regions = 4
2728
_x86_64_regions = 5
2829
_s390x_regions = 2
2930
_ppc64le_regions = 2
31+
_riscv64_regions = 4
3032

3133
@skipIfLLVMTargetMissing("AArch64")
3234
def test_aarch64(self):
@@ -58,6 +60,11 @@ def test_s390x(self):
5860
"""Test that lldb can read the process information from an s390x linux core file."""
5961
self.do_test("linux-s390x", self._s390x_pid, self._s390x_regions, "a.out")
6062

63+
@skipIfLLVMTargetMissing("RISCV")
64+
def test_riscv64(self):
65+
"""Test that lldb can read the process information from an riscv64 linux core file."""
66+
self.do_test("linux-riscv64", self._riscv64_pid, self._riscv64_regions, "a.out")
67+
6168
@skipIfLLVMTargetMissing("X86")
6269
def test_same_pid_running(self):
6370
"""Test that we read the information from the core correctly even if we have a running
@@ -629,6 +636,99 @@ def test_arm_core(self):
629636

630637
self.expect("register read --all")
631638

639+
@skipIfLLVMTargetMissing("RISCV")
640+
def test_riscv64_regs(self):
641+
# check basic registers using 64 bit RISC-V core file
642+
target = self.dbg.CreateTarget(None)
643+
self.assertTrue(target, VALID_TARGET)
644+
process = target.LoadCore("linux-riscv64.core")
645+
646+
values = {}
647+
values["pc"] = "0x000000000001015e"
648+
values["ra"] = "0x000000000001018c"
649+
values["sp"] = "0x0000003fffd132a0"
650+
values["gp"] = "0x0000002ae919af50"
651+
values["tp"] = "0x0000003fdceae3e0"
652+
values["t0"] = "0x0"
653+
values["t1"] = "0x0000002ae9187b1c"
654+
values["t2"] = "0x0000000000000021"
655+
values["fp"] = "0x0000003fffd132d0"
656+
values["s1"] = "0x0000002ae919cd98"
657+
values["a0"] = "0x0"
658+
values["a1"] = "0x0000000000010144"
659+
values["a2"] = "0x0000002ae919cdb0"
660+
values["a3"] = "0x000000000000002f"
661+
values["a4"] = "0x000000000000002f"
662+
values["a5"] = "0x0"
663+
values["a6"] = "0x7efefefefefefeff"
664+
values["a7"] = "0x00000000000000dd"
665+
values["s2"] = "0x0000002ae9196860"
666+
values["s3"] = "0x0000002ae919cdb0"
667+
values["s4"] = "0x0000003fffc63be8"
668+
values["s5"] = "0x0000002ae919cb78"
669+
values["s6"] = "0x0000002ae9196860"
670+
values["s7"] = "0x0000002ae9196860"
671+
values["s8"] = "0x0"
672+
values["s9"] = "0x000000000000000f"
673+
values["s10"] = "0x0000002ae919a8d0"
674+
values["s11"] = "0x0000000000000008"
675+
values["t3"] = "0x0000003fdce07df4"
676+
values["t4"] = "0x0"
677+
values["t5"] = "0x0000000000000020"
678+
values["t6"] = "0x0000002ae919f1b0"
679+
values["zero"] = "0x0"
680+
values["fcsr"] = "0x00000000"
681+
682+
fpr_names = {
683+
"ft0",
684+
"ft1",
685+
"ft2",
686+
"ft3",
687+
"ft4",
688+
"ft5",
689+
"ft6",
690+
"ft7",
691+
"ft8",
692+
"ft9",
693+
"ft10",
694+
"ft11",
695+
"fa0",
696+
"fa1",
697+
"fa2",
698+
"fa3",
699+
"fa4",
700+
"fa5",
701+
"fa6",
702+
"fa7",
703+
"fs0",
704+
"fs1",
705+
"fs2",
706+
"fs3",
707+
"fs4",
708+
"fs5",
709+
"fs6",
710+
"fs7",
711+
"fs8",
712+
"fs9",
713+
"fs10",
714+
"fs11",
715+
}
716+
fpr_value = "0x0000000000000000"
717+
718+
for regname, value in values.items():
719+
self.expect(
720+
"register read {}".format(regname),
721+
substrs=["{} = {}".format(regname, value)],
722+
)
723+
724+
for regname in fpr_names:
725+
self.expect(
726+
"register read {}".format(regname),
727+
substrs=["{} = {}".format(regname, fpr_value)],
728+
)
729+
730+
self.expect("register read --all")
731+
632732
def test_get_core_file_api(self):
633733
"""
634734
Test SBProcess::GetCoreFile() API can successfully get the core file.
Binary file not shown.
Binary file not shown.

0 commit comments

Comments
 (0)