Skip to content

[lldb][RISCV] Add RegisterContextPOSIXCore for RISC-V 64 #93297

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ RegisterContextPOSIX_riscv64::GetRegisterInfoAtIndex(size_t reg) {
}

size_t RegisterContextPOSIX_riscv64::GetRegisterSetCount() {
return m_register_info_up->GetRegisterCount();
return m_register_info_up->GetRegisterSetCount();
}

const lldb_private::RegisterSet *
Expand Down
1 change: 1 addition & 0 deletions lldb/source/Plugins/Process/elf-core/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ add_lldb_library(lldbPluginProcessElfCore PLUGIN
RegisterContextPOSIXCore_ppc64le.cpp
RegisterContextPOSIXCore_s390x.cpp
RegisterContextPOSIXCore_x86_64.cpp
RegisterContextPOSIXCore_riscv64.cpp
RegisterUtilities.cpp

LINK_LIBS
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
//===-- RegisterContextPOSIXCore_riscv64.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 "RegisterContextPOSIXCore_riscv64.h"

#include "lldb/Utility/DataBufferHeap.h"

using namespace lldb_private;

std::unique_ptr<RegisterContextCorePOSIX_riscv64>
RegisterContextCorePOSIX_riscv64::Create(Thread &thread, const ArchSpec &arch,
const DataExtractor &gpregset,
llvm::ArrayRef<CoreNote> notes) {
return std::unique_ptr<RegisterContextCorePOSIX_riscv64>(
new RegisterContextCorePOSIX_riscv64(
thread, std::make_unique<RegisterInfoPOSIX_riscv64>(arch, Flags()),
gpregset, notes));
}

RegisterContextCorePOSIX_riscv64::RegisterContextCorePOSIX_riscv64(
Thread &thread, std::unique_ptr<RegisterInfoPOSIX_riscv64> register_info,
const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
: RegisterContextPOSIX_riscv64(thread, std::move(register_info)) {

m_gpr_buffer = std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
gpregset.GetByteSize());
m_gpr.SetData(m_gpr_buffer);
m_gpr.SetByteOrder(gpregset.GetByteOrder());

ArchSpec arch = m_register_info_up->GetTargetArchitecture();
DataExtractor fpregset = getRegset(notes, arch.GetTriple(), FPR_Desc);
m_fpr_buffer = std::make_shared<DataBufferHeap>(fpregset.GetDataStart(),
fpregset.GetByteSize());
m_fpr.SetData(m_fpr_buffer);
m_fpr.SetByteOrder(fpregset.GetByteOrder());
}

RegisterContextCorePOSIX_riscv64::~RegisterContextCorePOSIX_riscv64() = default;

bool RegisterContextCorePOSIX_riscv64::ReadGPR() { return true; }

bool RegisterContextCorePOSIX_riscv64::ReadFPR() { return true; }

bool RegisterContextCorePOSIX_riscv64::WriteGPR() {
assert(false && "Writing registers is not allowed for core dumps");
return false;
}

bool RegisterContextCorePOSIX_riscv64::WriteFPR() {
assert(false && "Writing registers is not allowed for core dumps");
return false;
}

bool RegisterContextCorePOSIX_riscv64::ReadRegister(
const RegisterInfo *reg_info, RegisterValue &value) {
const uint8_t *src = nullptr;
lldb::offset_t offset = reg_info->byte_offset;

if (IsGPR(reg_info->kinds[lldb::eRegisterKindLLDB])) {
src = m_gpr.GetDataStart();
} else if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) {
src = m_fpr.GetDataStart();
offset -= GetGPRSize();
} else {
return false;
}

Status error;
value.SetFromMemoryData(*reg_info, src + offset, reg_info->byte_size,
lldb::eByteOrderLittle, error);
return error.Success();
}

bool RegisterContextCorePOSIX_riscv64::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &value) {
return false;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
//===-- RegisterContextPOSIXCore_riscv64.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_ELF_CORE_REGISTERCONTEXTPOSIXCORE_RISCV64_H
#define LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_RISCV64_H

#include "Plugins/Process/Utility/RegisterContextPOSIX_riscv64.h"
#include "Plugins/Process/Utility/RegisterInfoPOSIX_riscv64.h"

#include "Plugins/Process/elf-core/RegisterUtilities.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/RegisterValue.h"

#include <memory>

class RegisterContextCorePOSIX_riscv64 : public RegisterContextPOSIX_riscv64 {
public:
static std::unique_ptr<RegisterContextCorePOSIX_riscv64>
Create(lldb_private::Thread &thread, const lldb_private::ArchSpec &arch,
const lldb_private::DataExtractor &gpregset,
llvm::ArrayRef<lldb_private::CoreNote> notes);

~RegisterContextCorePOSIX_riscv64() 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;

protected:
RegisterContextCorePOSIX_riscv64(
lldb_private::Thread &thread,
std::unique_ptr<RegisterInfoPOSIX_riscv64> register_info,
const lldb_private::DataExtractor &gpregset,
llvm::ArrayRef<lldb_private::CoreNote> notes);

bool ReadGPR() override;

bool ReadFPR() override;

bool WriteGPR() override;

bool WriteFPR() override;

private:
lldb::DataBufferSP m_gpr_buffer;
lldb::DataBufferSP m_fpr_buffer;

lldb_private::DataExtractor m_gpr;
lldb_private::DataExtractor m_fpr;
};

#endif // LLDB_SOURCE_PLUGINS_PROCESS_ELF_CORE_REGISTERCONTEXTPOSIXCORE_RISCV64_H
8 changes: 7 additions & 1 deletion lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "RegisterContextPOSIXCore_mips64.h"
#include "RegisterContextPOSIXCore_powerpc.h"
#include "RegisterContextPOSIXCore_ppc64le.h"
#include "RegisterContextPOSIXCore_riscv64.h"
#include "RegisterContextPOSIXCore_s390x.h"
#include "RegisterContextPOSIXCore_x86_64.h"
#include "ThreadElfCore.h"
Expand Down Expand Up @@ -168,7 +169,8 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
}

if (!reg_interface && arch.GetMachine() != llvm::Triple::aarch64 &&
arch.GetMachine() != llvm::Triple::arm) {
arch.GetMachine() != llvm::Triple::arm &&
arch.GetMachine() != llvm::Triple::riscv64) {
LLDB_LOGF(log, "elf-core::%s:: Architecture(%d) or OS(%d) not supported",
__FUNCTION__, arch.GetMachine(), arch.GetTriple().getOS());
assert(false && "Architecture or OS not supported");
Expand All @@ -184,6 +186,10 @@ ThreadElfCore::CreateRegisterContextForFrame(StackFrame *frame) {
*this, std::make_unique<RegisterInfoPOSIX_arm>(arch), m_gpregset_data,
m_notes);
break;
case llvm::Triple::riscv64:
m_thread_reg_ctx_sp = RegisterContextCorePOSIX_riscv64::Create(
*this, arch, m_gpregset_data, m_notes);
break;
case llvm::Triple::mipsel:
case llvm::Triple::mips:
m_thread_reg_ctx_sp = std::make_shared<RegisterContextCorePOSIX_mips64>(
Expand Down
100 changes: 100 additions & 0 deletions lldb/test/API/functionalities/postmortem/elf-core/TestLinuxCore.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,14 @@ class LinuxCoreTestCase(TestBase):
_x86_64_pid = 32259
_s390x_pid = 1045
_ppc64le_pid = 28147
_riscv64_pid = 89328

_aarch64_regions = 4
_i386_regions = 4
_x86_64_regions = 5
_s390x_regions = 2
_ppc64le_regions = 2
_riscv64_regions = 4

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

@skipIfLLVMTargetMissing("RISCV")
def test_riscv64(self):
"""Test that lldb can read the process information from an riscv64 linux core file."""
self.do_test("linux-riscv64", self._riscv64_pid, self._riscv64_regions, "a.out")

@skipIfLLVMTargetMissing("X86")
def test_same_pid_running(self):
"""Test that we read the information from the core correctly even if we have a running
Expand Down Expand Up @@ -629,6 +636,99 @@ def test_arm_core(self):

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

@skipIfLLVMTargetMissing("RISCV")
def test_riscv64_regs(self):
# check basic registers using 64 bit RISC-V core file
target = self.dbg.CreateTarget(None)
self.assertTrue(target, VALID_TARGET)
process = target.LoadCore("linux-riscv64.core")

values = {}
values["pc"] = "0x000000000001015e"
values["ra"] = "0x000000000001018c"
values["sp"] = "0x0000003fffd132a0"
values["gp"] = "0x0000002ae919af50"
values["tp"] = "0x0000003fdceae3e0"
values["t0"] = "0x0"
values["t1"] = "0x0000002ae9187b1c"
values["t2"] = "0x0000000000000021"
values["fp"] = "0x0000003fffd132d0"
values["s1"] = "0x0000002ae919cd98"
values["a0"] = "0x0"
values["a1"] = "0x0000000000010144"
values["a2"] = "0x0000002ae919cdb0"
values["a3"] = "0x000000000000002f"
values["a4"] = "0x000000000000002f"
values["a5"] = "0x0"
values["a6"] = "0x7efefefefefefeff"
values["a7"] = "0x00000000000000dd"
values["s2"] = "0x0000002ae9196860"
values["s3"] = "0x0000002ae919cdb0"
values["s4"] = "0x0000003fffc63be8"
values["s5"] = "0x0000002ae919cb78"
values["s6"] = "0x0000002ae9196860"
values["s7"] = "0x0000002ae9196860"
values["s8"] = "0x0"
values["s9"] = "0x000000000000000f"
values["s10"] = "0x0000002ae919a8d0"
values["s11"] = "0x0000000000000008"
values["t3"] = "0x0000003fdce07df4"
values["t4"] = "0x0"
values["t5"] = "0x0000000000000020"
values["t6"] = "0x0000002ae919f1b0"
values["zero"] = "0x0"
values["fcsr"] = "0x00000000"

fpr_names = {
"ft0",
"ft1",
"ft2",
"ft3",
"ft4",
"ft5",
"ft6",
"ft7",
"ft8",
"ft9",
"ft10",
"ft11",
"fa0",
"fa1",
"fa2",
"fa3",
"fa4",
"fa5",
"fa6",
"fa7",
"fs0",
"fs1",
"fs2",
"fs3",
"fs4",
"fs5",
"fs6",
"fs7",
"fs8",
"fs9",
"fs10",
"fs11",
}
fpr_value = "0x0000000000000000"

for regname, value in values.items():
self.expect(
"register read {}".format(regname),
substrs=["{} = {}".format(regname, value)],
)

for regname in fpr_names:
self.expect(
"register read {}".format(regname),
substrs=["{} = {}".format(regname, fpr_value)],
)

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

def test_get_core_file_api(self):
"""
Test SBProcess::GetCoreFile() API can successfully get the core file.
Expand Down
Binary file not shown.
Binary file not shown.
Loading