[lldb][RISCV] Support optionally disabled FPR for riscv64 (#104547)
The PR adds the support optionally enabled/disabled FP-registers to LLDB `RegisterInfoPOSIX_riscv64`. This situation might take place for RISC-V builds having no FP-registers, like RV64IMAC or RV64IMACV. To aim this, patch adds `opt_regsets` flags mechanism. It re-works RegisterInfo class to work with flexibly allocated (depending on `opt_regsets` flag) `m_register_sets` and `m_register_infos` vectors instead of statically defined structures. The registration of regsets is being arranged by `m_per_regset_regnum_range` map. The patch flows are spread to `NativeRegisterContextLinux_riscv64` and `RegisterContextCorePOSIX_riscv64` classes, that were tested on: - x86_64 host working with coredumps - RV64GC and RV64IMAC targets working with coredumps and natively in run-time with binaries `EmulateInstructionRISCV` is out of scope of this patch, and its behavior did not change, using maximum set of registers. According testcase built for RV64IMAC (no-FPR) was added to `TestLinuxCore.py`.
This commit is contained in:
committed by
GitHub
parent
f7fa75b208
commit
660e34fd38
@@ -1748,10 +1748,10 @@ EmulateInstructionRISCV::GetRegisterInfo(RegisterKind reg_kind,
|
||||
}
|
||||
}
|
||||
|
||||
const RegisterInfo *array =
|
||||
RegisterInfoPOSIX_riscv64::GetRegisterInfoPtr(m_arch);
|
||||
const uint32_t length =
|
||||
RegisterInfoPOSIX_riscv64::GetRegisterInfoCount(m_arch);
|
||||
RegisterInfoPOSIX_riscv64 reg_info(m_arch,
|
||||
RegisterInfoPOSIX_riscv64::eRegsetMaskAll);
|
||||
const RegisterInfo *array = reg_info.GetRegisterInfo();
|
||||
const uint32_t length = reg_info.GetRegisterCount();
|
||||
|
||||
if (reg_index >= length || reg_kind != eRegisterKindLLDB)
|
||||
return {};
|
||||
|
||||
@@ -23,12 +23,11 @@
|
||||
|
||||
// System includes - They have to be included after framework includes because
|
||||
// they define some macros which collide with variable names in other modules
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/uio.h>
|
||||
// NT_PRSTATUS and NT_FPREGSET definition
|
||||
#include <elf.h>
|
||||
|
||||
#define REG_CONTEXT_SIZE (GetGPRSize() + GetFPRSize())
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
using namespace lldb_private::process_linux;
|
||||
@@ -38,7 +37,21 @@ NativeRegisterContextLinux::CreateHostNativeRegisterContextLinux(
|
||||
const ArchSpec &target_arch, NativeThreadLinux &native_thread) {
|
||||
switch (target_arch.GetMachine()) {
|
||||
case llvm::Triple::riscv64: {
|
||||
Flags opt_regsets;
|
||||
Flags opt_regsets(RegisterInfoPOSIX_riscv64::eRegsetMaskDefault);
|
||||
|
||||
RegisterInfoPOSIX_riscv64::FPR fpr;
|
||||
struct iovec ioVec;
|
||||
ioVec.iov_base = &fpr;
|
||||
ioVec.iov_len = sizeof(fpr);
|
||||
unsigned int regset = NT_FPREGSET;
|
||||
|
||||
if (NativeProcessLinux::PtraceWrapper(PTRACE_GETREGSET,
|
||||
native_thread.GetID(), ®set,
|
||||
&ioVec, sizeof(fpr))
|
||||
.Success()) {
|
||||
opt_regsets.Set(RegisterInfoPOSIX_riscv64::eRegsetMaskFP);
|
||||
}
|
||||
|
||||
auto register_info_up =
|
||||
std::make_unique<RegisterInfoPOSIX_riscv64>(target_arch, opt_regsets);
|
||||
return std::make_unique<NativeRegisterContextLinux_riscv64>(
|
||||
@@ -194,20 +207,23 @@ Status NativeRegisterContextLinux_riscv64::ReadAllRegisterValues(
|
||||
lldb::WritableDataBufferSP &data_sp) {
|
||||
Status error;
|
||||
|
||||
data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
|
||||
data_sp.reset(new DataBufferHeap(GetRegContextSize(), 0));
|
||||
|
||||
error = ReadGPR();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
|
||||
error = ReadFPR();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
if (GetRegisterInfo().IsFPPresent()) {
|
||||
error = ReadFPR();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t *dst = const_cast<uint8_t *>(data_sp->GetBytes());
|
||||
::memcpy(dst, GetGPRBuffer(), GetGPRSize());
|
||||
dst += GetGPRSize();
|
||||
::memcpy(dst, GetFPRBuffer(), GetFPRSize());
|
||||
if (GetRegisterInfo().IsFPPresent())
|
||||
::memcpy(dst, GetFPRBuffer(), GetFPRSize());
|
||||
|
||||
return error;
|
||||
}
|
||||
@@ -223,11 +239,11 @@ Status NativeRegisterContextLinux_riscv64::WriteAllRegisterValues(
|
||||
return error;
|
||||
}
|
||||
|
||||
if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
|
||||
if (data_sp->GetByteSize() != GetRegContextSize()) {
|
||||
error = Status::FromErrorStringWithFormat(
|
||||
"NativeRegisterContextLinux_riscv64::%s data_sp contained mismatched "
|
||||
"data size, expected %" PRIu64 ", actual %" PRIu64,
|
||||
__FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
|
||||
__FUNCTION__, GetRegContextSize(), data_sp->GetByteSize());
|
||||
return error;
|
||||
}
|
||||
|
||||
@@ -247,23 +263,32 @@ Status NativeRegisterContextLinux_riscv64::WriteAllRegisterValues(
|
||||
return error;
|
||||
|
||||
src += GetRegisterInfoInterface().GetGPRSize();
|
||||
::memcpy(GetFPRBuffer(), src, GetFPRSize());
|
||||
|
||||
error = WriteFPR();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
if (GetRegisterInfo().IsFPPresent()) {
|
||||
::memcpy(GetFPRBuffer(), src, GetFPRSize());
|
||||
|
||||
error = WriteFPR();
|
||||
if (error.Fail())
|
||||
return error;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
size_t NativeRegisterContextLinux_riscv64::GetRegContextSize() {
|
||||
size_t size = GetGPRSize();
|
||||
if (GetRegisterInfo().IsFPPresent())
|
||||
size += GetFPRSize();
|
||||
return size;
|
||||
}
|
||||
|
||||
bool NativeRegisterContextLinux_riscv64::IsGPR(unsigned reg) const {
|
||||
return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
|
||||
RegisterInfoPOSIX_riscv64::GPRegSet;
|
||||
}
|
||||
|
||||
bool NativeRegisterContextLinux_riscv64::IsFPR(unsigned reg) const {
|
||||
return GetRegisterInfo().GetRegisterSetFromRegisterIndex(reg) ==
|
||||
RegisterInfoPOSIX_riscv64::FPRegSet;
|
||||
return GetRegisterInfo().IsFPReg(reg);
|
||||
}
|
||||
|
||||
Status NativeRegisterContextLinux_riscv64::ReadGPR() {
|
||||
|
||||
@@ -75,6 +75,8 @@ private:
|
||||
|
||||
RegisterInfoPOSIX_riscv64::FPR m_fpr;
|
||||
|
||||
size_t GetRegContextSize();
|
||||
|
||||
bool IsGPR(unsigned reg) const;
|
||||
|
||||
bool IsFPR(unsigned reg) const;
|
||||
|
||||
@@ -77,6 +77,5 @@ bool RegisterContextPOSIX_riscv64::IsGPR(unsigned int reg) {
|
||||
}
|
||||
|
||||
bool RegisterContextPOSIX_riscv64::IsFPR(unsigned int reg) {
|
||||
return m_register_info_up->GetRegisterSetFromRegisterIndex(reg) ==
|
||||
RegisterInfoPOSIX_riscv64::FPRegSet;
|
||||
return m_register_info_up->IsFPReg(reg);
|
||||
}
|
||||
|
||||
@@ -18,42 +18,15 @@
|
||||
#define GPR_OFFSET(idx) ((idx)*8 + 0)
|
||||
#define FPR_OFFSET(idx) ((idx)*8 + sizeof(RegisterInfoPOSIX_riscv64::GPR))
|
||||
|
||||
#define REG_CONTEXT_SIZE \
|
||||
(sizeof(RegisterInfoPOSIX_riscv64::GPR) + \
|
||||
sizeof(RegisterInfoPOSIX_riscv64::FPR))
|
||||
|
||||
#define DECLARE_REGISTER_INFOS_RISCV64_STRUCT
|
||||
#include "RegisterInfos_riscv64.h"
|
||||
#undef DECLARE_REGISTER_INFOS_RISCV64_STRUCT
|
||||
|
||||
const lldb_private::RegisterInfo *RegisterInfoPOSIX_riscv64::GetRegisterInfoPtr(
|
||||
const lldb_private::ArchSpec &target_arch) {
|
||||
switch (target_arch.GetMachine()) {
|
||||
case llvm::Triple::riscv64:
|
||||
return g_register_infos_riscv64_le;
|
||||
default:
|
||||
assert(false && "Unhandled target architecture.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t RegisterInfoPOSIX_riscv64::GetRegisterInfoCount(
|
||||
const lldb_private::ArchSpec &target_arch) {
|
||||
switch (target_arch.GetMachine()) {
|
||||
case llvm::Triple::riscv64:
|
||||
return static_cast<uint32_t>(sizeof(g_register_infos_riscv64_le) /
|
||||
sizeof(g_register_infos_riscv64_le[0]));
|
||||
default:
|
||||
assert(false && "Unhandled target architecture.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Number of register sets provided by this context.
|
||||
enum {
|
||||
k_num_gpr_registers = gpr_last_riscv - gpr_first_riscv + 1,
|
||||
k_num_fpr_registers = fpr_last_riscv - fpr_first_riscv + 1,
|
||||
k_num_register_sets = 2
|
||||
k_num_register_sets_default = 1
|
||||
};
|
||||
|
||||
// RISC-V64 general purpose registers.
|
||||
@@ -73,38 +46,69 @@ static_assert(((sizeof g_gpr_regnums_riscv64 /
|
||||
1) == k_num_gpr_registers,
|
||||
"g_gpr_regnums_riscv64 has wrong number of register infos");
|
||||
|
||||
// RISC-V64 floating point registers.
|
||||
static const uint32_t g_fpr_regnums_riscv64[] = {
|
||||
fpr_f0_riscv, fpr_f1_riscv, fpr_f2_riscv, fpr_f3_riscv,
|
||||
fpr_f4_riscv, fpr_f5_riscv, fpr_f6_riscv, fpr_f7_riscv,
|
||||
fpr_f8_riscv, fpr_f9_riscv, fpr_f10_riscv, fpr_f11_riscv,
|
||||
fpr_f12_riscv, fpr_f13_riscv, fpr_f14_riscv, fpr_f15_riscv,
|
||||
fpr_f16_riscv, fpr_f17_riscv, fpr_f18_riscv, fpr_f19_riscv,
|
||||
fpr_f20_riscv, fpr_f21_riscv, fpr_f22_riscv, fpr_f23_riscv,
|
||||
fpr_f24_riscv, fpr_f25_riscv, fpr_f26_riscv, fpr_f27_riscv,
|
||||
fpr_f28_riscv, fpr_f29_riscv, fpr_f30_riscv, fpr_f31_riscv,
|
||||
fpr_fcsr_riscv, LLDB_INVALID_REGNUM};
|
||||
|
||||
static_assert(((sizeof g_fpr_regnums_riscv64 /
|
||||
sizeof g_fpr_regnums_riscv64[0]) -
|
||||
1) == k_num_fpr_registers,
|
||||
"g_fpr_regnums_riscv64 has wrong number of register infos");
|
||||
|
||||
// Register sets for RISC-V64.
|
||||
static const lldb_private::RegisterSet g_reg_sets_riscv64[k_num_register_sets] =
|
||||
{{"General Purpose Registers", "gpr", k_num_gpr_registers,
|
||||
g_gpr_regnums_riscv64},
|
||||
{"Floating Point Registers", "fpr", k_num_fpr_registers,
|
||||
g_fpr_regnums_riscv64}};
|
||||
static const lldb_private::RegisterSet g_reg_set_gpr_riscv64 = {
|
||||
"General Purpose Registers", "gpr", k_num_gpr_registers,
|
||||
g_gpr_regnums_riscv64};
|
||||
static const lldb_private::RegisterSet g_reg_set_fpr_riscv64 = {
|
||||
"Floating Point Registers", "fpr", k_num_fpr_registers, nullptr};
|
||||
|
||||
RegisterInfoPOSIX_riscv64::RegisterInfoPOSIX_riscv64(
|
||||
const lldb_private::ArchSpec &target_arch, lldb_private::Flags flags)
|
||||
const lldb_private::ArchSpec &target_arch, lldb_private::Flags opt_regsets)
|
||||
: lldb_private::RegisterInfoAndSetInterface(target_arch),
|
||||
m_register_info_p(GetRegisterInfoPtr(target_arch)),
|
||||
m_register_info_count(GetRegisterInfoCount(target_arch)) {}
|
||||
m_opt_regsets(opt_regsets) {
|
||||
switch (target_arch.GetMachine()) {
|
||||
case llvm::Triple::riscv64: {
|
||||
// By-default considering RISC-V has only GPR.
|
||||
// Other register sets could be enabled optionally by opt_regsets.
|
||||
AddRegSetGP();
|
||||
|
||||
if (m_opt_regsets.AnySet(eRegsetMaskFP))
|
||||
AddRegSetFP();
|
||||
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(false && "Unhandled target architecture.");
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterInfoPOSIX_riscv64::AddRegSetGP() {
|
||||
m_register_infos.resize(k_num_gpr_registers);
|
||||
memcpy(&m_register_infos[0], g_register_infos_riscv64_gpr,
|
||||
sizeof(g_register_infos_riscv64_gpr));
|
||||
m_register_sets.push_back(g_reg_set_gpr_riscv64);
|
||||
|
||||
m_per_regset_regnum_range[GPRegSet] =
|
||||
std::make_pair(gpr_first_riscv, m_register_infos.size());
|
||||
}
|
||||
|
||||
void RegisterInfoPOSIX_riscv64::AddRegSetFP() {
|
||||
const uint32_t register_info_count = m_register_infos.size();
|
||||
const uint32_t register_set_count = m_register_sets.size();
|
||||
|
||||
// Filling m_register_infos.
|
||||
// For FPR case we do not need to correct register offsets and kinds
|
||||
// while for other further cases (like VPR), register offset/kind
|
||||
// should be started counting from the last one in previously added
|
||||
// regset. This is needed for the case e.g. when architecture has GPR + VPR
|
||||
// sets only.
|
||||
m_register_infos.resize(register_info_count + k_num_fpr_registers);
|
||||
memcpy(&m_register_infos[register_info_count], g_register_infos_riscv64_fpr,
|
||||
sizeof(g_register_infos_riscv64_fpr));
|
||||
|
||||
// Filling m_register_sets with enabled register set
|
||||
for (uint32_t i = 0; i < k_num_fpr_registers; i++)
|
||||
m_fp_regnum_collection.push_back(register_info_count + i);
|
||||
m_register_sets.push_back(g_reg_set_fpr_riscv64);
|
||||
m_register_sets.back().registers = m_fp_regnum_collection.data();
|
||||
|
||||
m_per_regset_regnum_range[register_set_count] =
|
||||
std::make_pair(register_info_count, m_register_infos.size());
|
||||
}
|
||||
|
||||
uint32_t RegisterInfoPOSIX_riscv64::GetRegisterCount() const {
|
||||
return m_register_info_count;
|
||||
return m_register_infos.size();
|
||||
}
|
||||
|
||||
size_t RegisterInfoPOSIX_riscv64::GetGPRSize() const {
|
||||
@@ -117,26 +121,30 @@ size_t RegisterInfoPOSIX_riscv64::GetFPRSize() const {
|
||||
|
||||
const lldb_private::RegisterInfo *
|
||||
RegisterInfoPOSIX_riscv64::GetRegisterInfo() const {
|
||||
return m_register_info_p;
|
||||
return m_register_infos.data();
|
||||
}
|
||||
|
||||
size_t RegisterInfoPOSIX_riscv64::GetRegisterSetCount() const {
|
||||
return k_num_register_sets;
|
||||
return m_register_sets.size();
|
||||
}
|
||||
|
||||
size_t RegisterInfoPOSIX_riscv64::GetRegisterSetFromRegisterIndex(
|
||||
uint32_t reg_index) const {
|
||||
// coverity[unsigned_compare]
|
||||
if (reg_index >= gpr_first_riscv && reg_index <= gpr_last_riscv)
|
||||
return GPRegSet;
|
||||
if (reg_index >= fpr_first_riscv && reg_index <= fpr_last_riscv)
|
||||
return FPRegSet;
|
||||
for (const auto ®set_range : m_per_regset_regnum_range) {
|
||||
if (reg_index >= regset_range.second.first &&
|
||||
reg_index < regset_range.second.second)
|
||||
return regset_range.first;
|
||||
}
|
||||
return LLDB_INVALID_REGNUM;
|
||||
}
|
||||
|
||||
bool RegisterInfoPOSIX_riscv64::IsFPReg(unsigned reg) const {
|
||||
return llvm::is_contained(m_fp_regnum_collection, reg);
|
||||
}
|
||||
|
||||
const lldb_private::RegisterSet *
|
||||
RegisterInfoPOSIX_riscv64::GetRegisterSet(size_t set_index) const {
|
||||
if (set_index < GetRegisterSetCount())
|
||||
return &g_reg_sets_riscv64[set_index];
|
||||
return &m_register_sets[set_index];
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@@ -11,19 +11,21 @@
|
||||
|
||||
#include "RegisterInfoAndSetInterface.h"
|
||||
#include "lldb/Target/RegisterContext.h"
|
||||
#include "lldb/Utility/Flags.h"
|
||||
#include "lldb/lldb-private.h"
|
||||
#include <map>
|
||||
|
||||
class RegisterInfoPOSIX_riscv64
|
||||
: public lldb_private::RegisterInfoAndSetInterface {
|
||||
public:
|
||||
static const lldb_private::RegisterInfo *
|
||||
GetRegisterInfoPtr(const lldb_private::ArchSpec &target_arch);
|
||||
static uint32_t
|
||||
GetRegisterInfoCount(const lldb_private::ArchSpec &target_arch);
|
||||
enum { GPRegSet = 0 };
|
||||
|
||||
public:
|
||||
enum { GPRegSet = 0, FPRegSet };
|
||||
// RISC-V64 register set mask value
|
||||
enum {
|
||||
eRegsetMaskDefault = 0,
|
||||
eRegsetMaskFP = 1,
|
||||
eRegsetMaskAll = -1,
|
||||
};
|
||||
|
||||
struct GPR {
|
||||
// note: gpr[0] is pc, not x0
|
||||
@@ -41,7 +43,11 @@ public:
|
||||
};
|
||||
|
||||
RegisterInfoPOSIX_riscv64(const lldb_private::ArchSpec &target_arch,
|
||||
lldb_private::Flags flags);
|
||||
lldb_private::Flags opt_regsets);
|
||||
|
||||
void AddRegSetGP();
|
||||
|
||||
void AddRegSetFP();
|
||||
|
||||
size_t GetGPRSize() const override;
|
||||
|
||||
@@ -58,9 +64,23 @@ public:
|
||||
|
||||
size_t GetRegisterSetFromRegisterIndex(uint32_t reg_index) const override;
|
||||
|
||||
bool IsFPPresent() const { return m_opt_regsets.AnySet(eRegsetMaskFP); }
|
||||
|
||||
bool IsFPReg(unsigned reg) const;
|
||||
|
||||
private:
|
||||
const lldb_private::RegisterInfo *m_register_info_p;
|
||||
uint32_t m_register_info_count;
|
||||
std::vector<lldb_private::RegisterInfo> m_register_infos;
|
||||
|
||||
std::vector<lldb_private::RegisterSet> m_register_sets;
|
||||
|
||||
// Contains pair of [start, end] register numbers of a register set with start
|
||||
// and end included.
|
||||
std::map<uint32_t, std::pair<uint32_t, uint32_t>> m_per_regset_regnum_range;
|
||||
|
||||
// Register collections to be stored as reference for m_register_sets items
|
||||
std::vector<uint32_t> m_fp_regnum_collection;
|
||||
|
||||
lldb_private::Flags m_opt_regsets;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -79,7 +79,7 @@ using namespace riscv_dwarf;
|
||||
|
||||
// clang-format on
|
||||
|
||||
static lldb_private::RegisterInfo g_register_infos_riscv64_le[] = {
|
||||
static lldb_private::RegisterInfo g_register_infos_riscv64_gpr[] = {
|
||||
// DEFINE_GPR64(name, GENERIC KIND)
|
||||
DEFINE_GPR64(pc, LLDB_REGNUM_GENERIC_PC),
|
||||
DEFINE_GPR64_ALT(ra, x1, LLDB_REGNUM_GENERIC_RA),
|
||||
@@ -114,7 +114,9 @@ static lldb_private::RegisterInfo g_register_infos_riscv64_le[] = {
|
||||
DEFINE_GPR64_ALT(t5, x30, LLDB_INVALID_REGNUM),
|
||||
DEFINE_GPR64_ALT(t6, x31, LLDB_INVALID_REGNUM),
|
||||
DEFINE_GPR64_ALT(zero, x0, LLDB_INVALID_REGNUM),
|
||||
};
|
||||
|
||||
static lldb_private::RegisterInfo g_register_infos_riscv64_fpr[] = {
|
||||
DEFINE_FPR64_ALT(ft0, f0, LLDB_INVALID_REGNUM),
|
||||
DEFINE_FPR64_ALT(ft1, f1, LLDB_INVALID_REGNUM),
|
||||
DEFINE_FPR64_ALT(ft2, f2, LLDB_INVALID_REGNUM),
|
||||
@@ -148,39 +150,25 @@ static lldb_private::RegisterInfo g_register_infos_riscv64_le[] = {
|
||||
DEFINE_FPR64_ALT(ft10, f30, LLDB_INVALID_REGNUM),
|
||||
DEFINE_FPR64_ALT(ft11, f31, LLDB_INVALID_REGNUM),
|
||||
DEFINE_FPR_ALT(fcsr, nullptr, 4, LLDB_INVALID_REGNUM),
|
||||
};
|
||||
|
||||
DEFINE_VPR(v0, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v1, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v2, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v3, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v4, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v5, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v6, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v7, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v8, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v9, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v10, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v11, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v12, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v13, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v14, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v15, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v16, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v17, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v18, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v19, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v20, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v21, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v22, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v23, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v24, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v25, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v26, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v27, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v28, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v29, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v30, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v31, LLDB_INVALID_REGNUM),
|
||||
static lldb_private::RegisterInfo g_register_infos_riscv64_vpr[] = {
|
||||
DEFINE_VPR(v0, LLDB_INVALID_REGNUM), DEFINE_VPR(v1, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v2, LLDB_INVALID_REGNUM), DEFINE_VPR(v3, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v4, LLDB_INVALID_REGNUM), DEFINE_VPR(v5, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v6, LLDB_INVALID_REGNUM), DEFINE_VPR(v7, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v8, LLDB_INVALID_REGNUM), DEFINE_VPR(v9, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v10, LLDB_INVALID_REGNUM), DEFINE_VPR(v11, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v12, LLDB_INVALID_REGNUM), DEFINE_VPR(v13, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v14, LLDB_INVALID_REGNUM), DEFINE_VPR(v15, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v16, LLDB_INVALID_REGNUM), DEFINE_VPR(v17, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v18, LLDB_INVALID_REGNUM), DEFINE_VPR(v19, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v20, LLDB_INVALID_REGNUM), DEFINE_VPR(v21, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v22, LLDB_INVALID_REGNUM), DEFINE_VPR(v23, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v24, LLDB_INVALID_REGNUM), DEFINE_VPR(v25, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v26, LLDB_INVALID_REGNUM), DEFINE_VPR(v27, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v28, LLDB_INVALID_REGNUM), DEFINE_VPR(v29, LLDB_INVALID_REGNUM),
|
||||
DEFINE_VPR(v30, LLDB_INVALID_REGNUM), DEFINE_VPR(v31, LLDB_INVALID_REGNUM),
|
||||
};
|
||||
|
||||
#endif // DECLARE_REGISTER_INFOS_RISCV64_STRUCT
|
||||
|
||||
@@ -16,9 +16,17 @@ std::unique_ptr<RegisterContextCorePOSIX_riscv64>
|
||||
RegisterContextCorePOSIX_riscv64::Create(Thread &thread, const ArchSpec &arch,
|
||||
const DataExtractor &gpregset,
|
||||
llvm::ArrayRef<CoreNote> notes) {
|
||||
Flags opt_regsets = RegisterInfoPOSIX_riscv64::eRegsetMaskDefault;
|
||||
|
||||
DataExtractor fpregset = getRegset(notes, arch.GetTriple(), FPR_Desc);
|
||||
if (fpregset.GetByteSize() >= sizeof(uint64_t)) {
|
||||
opt_regsets.Set(RegisterInfoPOSIX_riscv64::eRegsetMaskFP);
|
||||
}
|
||||
|
||||
return std::unique_ptr<RegisterContextCorePOSIX_riscv64>(
|
||||
new RegisterContextCorePOSIX_riscv64(
|
||||
thread, std::make_unique<RegisterInfoPOSIX_riscv64>(arch, Flags()),
|
||||
thread,
|
||||
std::make_unique<RegisterInfoPOSIX_riscv64>(arch, opt_regsets),
|
||||
gpregset, notes));
|
||||
}
|
||||
|
||||
@@ -27,17 +35,14 @@ RegisterContextCorePOSIX_riscv64::RegisterContextCorePOSIX_riscv64(
|
||||
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.SetData(std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
|
||||
gpregset.GetByteSize()));
|
||||
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());
|
||||
if (m_register_info_up->IsFPPresent()) {
|
||||
ArchSpec arch = m_register_info_up->GetTargetArchitecture();
|
||||
m_fpr = getRegset(notes, arch.GetTriple(), FPR_Desc);
|
||||
}
|
||||
}
|
||||
|
||||
RegisterContextCorePOSIX_riscv64::~RegisterContextCorePOSIX_riscv64() = default;
|
||||
|
||||
@@ -50,9 +50,6 @@ protected:
|
||||
bool WriteFPR() override;
|
||||
|
||||
private:
|
||||
lldb::DataBufferSP m_gpr_buffer;
|
||||
lldb::DataBufferSP m_fpr_buffer;
|
||||
|
||||
lldb_private::DataExtractor m_gpr;
|
||||
lldb_private::DataExtractor m_fpr;
|
||||
};
|
||||
|
||||
@@ -21,7 +21,8 @@ class LinuxCoreTestCase(TestBase):
|
||||
_x86_64_pid = 32259
|
||||
_s390x_pid = 1045
|
||||
_ppc64le_pid = 28147
|
||||
_riscv64_pid = 89328
|
||||
_riscv64_gpr_fpr_pid = 1089
|
||||
_riscv64_gpr_only_pid = 97
|
||||
|
||||
_aarch64_regions = 4
|
||||
_i386_regions = 4
|
||||
@@ -61,9 +62,25 @@ class LinuxCoreTestCase(TestBase):
|
||||
self.do_test("linux-s390x", self._s390x_pid, self._s390x_regions, "a.out")
|
||||
|
||||
@skipIfLLVMTargetMissing("RISCV")
|
||||
def test_riscv64(self):
|
||||
def test_riscv64_gpr_fpr(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")
|
||||
self.do_test(
|
||||
"linux-riscv64.gpr_fpr",
|
||||
self._riscv64_gpr_fpr_pid,
|
||||
self._riscv64_regions,
|
||||
"a.out",
|
||||
)
|
||||
|
||||
@skipIfLLVMTargetMissing("RISCV")
|
||||
def test_riscv64_gpr_only(self):
|
||||
"""Test that lldb can read the process information from an riscv64 linux core file
|
||||
made for a RV64IMAC target, having no FP-registers."""
|
||||
self.do_test(
|
||||
"linux-riscv64.gpr_only",
|
||||
self._riscv64_gpr_only_pid,
|
||||
self._riscv64_regions,
|
||||
"a.out",
|
||||
)
|
||||
|
||||
@skipIfLLVMTargetMissing("X86")
|
||||
def test_same_pid_running(self):
|
||||
@@ -668,46 +685,47 @@ class LinuxCoreTestCase(TestBase):
|
||||
self.expect("register read --all")
|
||||
|
||||
@skipIfLLVMTargetMissing("RISCV")
|
||||
def test_riscv64_regs(self):
|
||||
def test_riscv64_regs_gpr_fpr(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")
|
||||
process = target.LoadCore("linux-riscv64.gpr_fpr.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["pc"] = "0x000000000001016e"
|
||||
values["ra"] = "0x00000000000101a4"
|
||||
values["sp"] = "0x0000003fffc1d2d0"
|
||||
values["gp"] = "0x0000002ae6eccf50"
|
||||
values["tp"] = "0x0000003ff3cb5400"
|
||||
values["t0"] = "0x7f7f7f7fffffffff"
|
||||
values["t1"] = "0x0000002ae6eb9b1c"
|
||||
values["t2"] = "0xffffffffffffffff"
|
||||
values["fp"] = "0x0000003fffc1d300"
|
||||
values["s1"] = "0x0000002ae6eced98"
|
||||
values["a0"] = "0x0"
|
||||
values["a1"] = "0x0000000000010144"
|
||||
values["a2"] = "0x0000002ae919cdb0"
|
||||
values["a3"] = "0x000000000000002f"
|
||||
values["a4"] = "0x000000000000002f"
|
||||
values["a2"] = "0x0000002ae6ecedb0"
|
||||
values["a3"] = "0xafdbdbff81cf7f81"
|
||||
values["a4"] = "0x00000000000101e4"
|
||||
values["a5"] = "0x0"
|
||||
values["a6"] = "0x7efefefefefefeff"
|
||||
values["a6"] = "0x2f5b5a40014e0001"
|
||||
values["a7"] = "0x00000000000000dd"
|
||||
values["s2"] = "0x0000002ae9196860"
|
||||
values["s3"] = "0x0000002ae919cdb0"
|
||||
values["s4"] = "0x0000003fffc63be8"
|
||||
values["s5"] = "0x0000002ae919cb78"
|
||||
values["s6"] = "0x0000002ae9196860"
|
||||
values["s7"] = "0x0000002ae9196860"
|
||||
values["s2"] = "0x0000002ae6ec8860"
|
||||
values["s3"] = "0x0000002ae6ecedb0"
|
||||
values["s4"] = "0x0000003fff886c18"
|
||||
values["s5"] = "0x0000002ae6eceb78"
|
||||
values["s6"] = "0x0000002ae6ec8860"
|
||||
values["s7"] = "0x0000002ae6ec8860"
|
||||
values["s8"] = "0x0"
|
||||
values["s9"] = "0x000000000000000f"
|
||||
values["s10"] = "0x0000002ae919a8d0"
|
||||
values["s10"] = "0x0000002ae6ecc8d0"
|
||||
values["s11"] = "0x0000000000000008"
|
||||
values["t3"] = "0x0000003fdce07df4"
|
||||
values["t3"] = "0x0000003ff3be3728"
|
||||
values["t4"] = "0x0"
|
||||
values["t5"] = "0x0000000000000020"
|
||||
values["t6"] = "0x0000002ae919f1b0"
|
||||
values["t5"] = "0x0000000000000002"
|
||||
values["t6"] = "0x0000002ae6ed08b9"
|
||||
values["zero"] = "0x0"
|
||||
values["fa5"] = "0xffffffff423c0000"
|
||||
values["fcsr"] = "0x00000000"
|
||||
|
||||
fpr_names = {
|
||||
@@ -728,7 +746,7 @@ class LinuxCoreTestCase(TestBase):
|
||||
"fa2",
|
||||
"fa3",
|
||||
"fa4",
|
||||
"fa5",
|
||||
# fa5 is non-zero and checked in the list above.
|
||||
"fa6",
|
||||
"fa7",
|
||||
"fs0",
|
||||
@@ -760,6 +778,61 @@ class LinuxCoreTestCase(TestBase):
|
||||
|
||||
self.expect("register read --all")
|
||||
|
||||
@skipIfLLVMTargetMissing("RISCV")
|
||||
def test_riscv64_regs_gpr_only(self):
|
||||
# check registers using 64 bit RISC-V core file containing GP-registers only
|
||||
target = self.dbg.CreateTarget(None)
|
||||
self.assertTrue(target, VALID_TARGET)
|
||||
process = target.LoadCore("linux-riscv64.gpr_only.core")
|
||||
|
||||
values = {}
|
||||
values["pc"] = "0x0000000000010164"
|
||||
values["ra"] = "0x0000000000010194"
|
||||
values["sp"] = "0x00fffffff4d5fcc0"
|
||||
values["gp"] = "0x0000000000157678"
|
||||
values["tp"] = "0x00ffffff99c43400"
|
||||
values["t0"] = "0x00ffffff99c6b260"
|
||||
values["t1"] = "0x00ffffff99b7bd54"
|
||||
values["t2"] = "0x0000000003f0b27f"
|
||||
values["fp"] = "0x00fffffff4d5fcf0"
|
||||
values["s1"] = "0x0000000000000003"
|
||||
values["a0"] = "0x0"
|
||||
values["a1"] = "0x0000000000010144"
|
||||
values["a2"] = "0x0000000000176460"
|
||||
values["a3"] = "0x000000000015ee38"
|
||||
values["a4"] = "0x00000000423c0000"
|
||||
values["a5"] = "0x0"
|
||||
values["a6"] = "0x0"
|
||||
values["a7"] = "0x00000000000000dd"
|
||||
values["s2"] = "0x0"
|
||||
values["s3"] = "0x000000000014ddf8"
|
||||
values["s4"] = "0x000000000003651c"
|
||||
values["s5"] = "0x00fffffffccd8d28"
|
||||
values["s6"] = "0x000000000014ddf8"
|
||||
values["s7"] = "0x00ffffff99c69d48"
|
||||
values["s8"] = "0x00ffffff99c6a008"
|
||||
values["s9"] = "0x0"
|
||||
values["s10"] = "0x0"
|
||||
values["s11"] = "0x0"
|
||||
values["t3"] = "0x00ffffff99c42000"
|
||||
values["t4"] = "0x00ffffff99af8e20"
|
||||
values["t5"] = "0x0000000000000005"
|
||||
values["t6"] = "0x44760bdd8d5f6381"
|
||||
values["zero"] = "0x0"
|
||||
|
||||
for regname, value in values.items():
|
||||
self.expect(
|
||||
"register read {}".format(regname),
|
||||
substrs=["{} = {}".format(regname, value)],
|
||||
)
|
||||
|
||||
# Check that LLDB does not try to read other registers from core file
|
||||
self.expect(
|
||||
"register read --all",
|
||||
matching=False,
|
||||
substrs=["registers were unavailable"],
|
||||
)
|
||||
|
||||
def test_get_core_file_api(self):
|
||||
"""
|
||||
Test SBProcess::GetCoreFile() API can successfully get the core file.
|
||||
|
||||
Binary file not shown.
BIN
lldb/test/API/functionalities/postmortem/elf-core/linux-riscv64.gpr_fpr.out
Executable file
BIN
lldb/test/API/functionalities/postmortem/elf-core/linux-riscv64.gpr_fpr.out
Executable file
Binary file not shown.
Binary file not shown.
BIN
lldb/test/API/functionalities/postmortem/elf-core/linux-riscv64.gpr_only.out
Executable file
BIN
lldb/test/API/functionalities/postmortem/elf-core/linux-riscv64.gpr_only.out
Executable file
Binary file not shown.
Binary file not shown.
14
lldb/test/API/functionalities/postmortem/elf-core/main_fpr.c
Normal file
14
lldb/test/API/functionalities/postmortem/elf-core/main_fpr.c
Normal file
@@ -0,0 +1,14 @@
|
||||
static void bar(float *boom) {
|
||||
float F = 98.0;
|
||||
*boom = 47.0; // Frame bar
|
||||
}
|
||||
|
||||
static void foo(float *boom, void (*boomer)(float *)) {
|
||||
float F = 102.0;
|
||||
boomer(boom); // Frame foo
|
||||
}
|
||||
|
||||
void _start(void) {
|
||||
float F = 95.0;
|
||||
foo(0, bar); // Frame _start
|
||||
}
|
||||
Reference in New Issue
Block a user