15#include "llvm/ADT/STLExtras.h"
16#include "llvm/IR/DerivedTypes.h"
28#define DEFINE_REG_NAME(reg_num) ConstString(#reg_num).GetCString()
29#define DEFINE_REG_NAME_STR(reg_name) ConstString(reg_name).GetCString()
34#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num) \
36 DEFINE_REG_NAME(dwarf_num), DEFINE_REG_NAME_STR(str_name), 0, 0, \
37 eEncodingInvalid, eFormatDefault, \
38 {dwarf_num, dwarf_num, generic_num, LLDB_INVALID_REGNUM, dwarf_num}, \
39 nullptr, nullptr, nullptr, \
42#define DEFINE_REGISTER_STUB(dwarf_num, str_name) \
43 DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, LLDB_INVALID_REGNUM)
131 count = dwarf::g_register_infos.size();
132 return dwarf::g_register_infos.data();
141 llvm::Triple::ArchType machine = arch.
GetTriple().getArch();
143 if (llvm::Triple::riscv32 != machine && llvm::Triple::riscv64 != machine)
149 abi->
SetIsRV64((llvm::Triple::riscv64 == machine) ?
true :
false);
155 return llvm::alignTo(size_in_bytes,
word_size);
160 const llvm::ArrayRef<ABI::CallArgument> &args) {
163 size_t total_size = 0;
164 for (
const auto &arg : args)
176 const uint32_t reg_num,
const addr_t value) {
182 static_cast<uint64_t
>(value));
192 const llvm::ArrayRef<addr_t> args) {
193 std::stringstream ss;
194 ss <<
"ABISysV_riscv::PrepareTrivialCall"
195 <<
" (tid = 0x" << std::hex << thread.GetID() <<
", sp = 0x" <<
sp
196 <<
", func_addr = 0x" << func_addr <<
", return_addr = 0x" << return_addr;
198 for (
auto [idx, arg] : enumerate(args))
199 ss <<
", arg" << std::dec << idx <<
" = 0x" << std::hex << arg;
206 llvm::ArrayRef<addr_t> args)
const {
207 Log *log =
GetLog(LLDBLog::Expressions);
213 LLDB_LOG(log,
"Failed to get RegisterContext");
218 LLDB_LOG(log,
"Function has {0} arguments, but only {1} are allowed!",
224 for (
auto [idx, arg] : enumerate(args)) {
225 const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(
227 LLDB_LOG(log,
"About to write arg{0} (0x{1:x}) into {2}", idx, arg,
230 if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) {
231 LLDB_LOG(log,
"Failed to write arg{0} (0x{1:x}) into {2}", idx, arg,
247 LLDB_LOG(log,
"ABISysV_riscv::{0}() success", __FUNCTION__);
253 llvm::ArrayRef<ABI::CallArgument> args)
const {
258 uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
263 uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
268 uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
281 for (
const auto &arg : args) {
289 if (process->WriteMemory(
sp, arg.data_up.get(), arg.size,
error) <
295 *
const_cast<addr_t *
>(&arg.value) =
sp;
299 assert(prototype.getFunctionNumParams() == args.size());
301 const size_t num_args = args.size();
302 const size_t num_args_in_regs =
312 uint8_t reg_value[8];
315 for (
size_t i = 0; i < args_size; ++i) {
316 auto value =
reinterpret_cast<const uint8_t *
>(&args[i].value);
321 if (i < num_args_in_regs) {
324 memcpy(reg_value, value, end);
326 memset(reg_value + end, 0,
reg_size - end);
328 RegisterValue reg_val_obj(llvm::ArrayRef(reg_value,
reg_size),
330 if (!reg_ctx->WriteRegister(
344 if (process->WriteMemory(
sp - offset, value, size,
error) < size ||
355 reg_ctx->WriteRegisterFromUnsigned(pc_reg,
pc);
356 reg_ctx->WriteRegisterFromUnsigned(ra_reg,
ra);
357 reg_ctx->WriteRegisterFromUnsigned(sp_reg,
sp);
375 CompilerType compiler_type = new_value_sp->GetCompilerType();
376 if (!compiler_type) {
381 auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext();
383 bool is_signed =
false;
387 "We don't support returning other types at present");
392 size_t num_bytes = new_value_sp->
GetData(data, result);
396 "Couldn't convert return value to raw data: %s", result.
AsCString());
403 uint64_t raw_value = data.
GetMaxU64(&offset, num_bytes);
407 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
409 "Couldn't write value to register %s", reg_info->
name);
424 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
426 "Couldn't write value to register %s", reg_info->
name);
433 "We don't support returning large integer values at present.");
439 raw_value &= std::numeric_limits<T>::max();
441 scalar =
static_cast<typename std::make_signed<T>::type
>(raw_value);
443 scalar =
static_cast<T
>(raw_value);
447 uint8_t size_in_bytes,
bool is_signed) {
448 switch (size_in_bytes) {
452 case sizeof(uint64_t):
456 case sizeof(uint32_t):
460 case sizeof(uint16_t):
464 case sizeof(uint8_t):
473 uint8_t size_in_bytes) {
474 switch (size_in_bytes) {
478 case sizeof(uint64_t):
479 scalar = *
reinterpret_cast<double *
>(&raw_value);
482 case sizeof(uint32_t):
483 scalar = *
reinterpret_cast<float *
>(&raw_value);
492 llvm::Triple::ArchType machine,
494 uint32_t byte_size) {
504 case sizeof(uint32_t):
506 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
508 case sizeof(uint64_t):
510 if (llvm::Triple::riscv32 == machine) {
511 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
513 (reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) &
UINT32_MAX) << 32U;
515 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
520 if (llvm::Triple::riscv32 == machine)
521 return return_valobj_sp;
524 std::unique_ptr<DataBufferHeap> heap_data_up(
526 const ByteOrder byte_order = thread.GetProcess()->GetByteOrder();
528 if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&
529 reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {
532 heap_data_up->GetBytes() + 0, 8,
533 byte_order,
error) &&
535 heap_data_up->GetBytes() + 8, 8,
536 byte_order,
error)) {
537 value.
SetBytes(heap_data_up.release(), byte_size);
539 thread.GetStackFrameAtIndex(0).get(), value,
ConstString(
""));
545 return return_valobj_sp;
548 if (type_flags & eTypeIsInteger) {
549 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
551 return return_valobj_sp;
552 }
else if (type_flags & eTypeIsFloat) {
554 return return_valobj_sp;
556 return return_valobj_sp;
560 thread.GetStackFrameAtIndex(0).get(), value,
ConstString(
""));
561 return return_valobj_sp;
566 llvm::Triple::ArchType machine, uint32_t arch_fp_flags,
567 uint32_t type_flags, uint32_t byte_size) {
568 auto reg_info_fa0 = reg_ctx->GetRegisterInfoByName(
"fa0");
569 bool use_fp_regs =
false;
572 switch (arch_fp_flags) {
577 return return_valobj_sp;
597 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);
599 return return_valobj_sp;
614 return return_valobj_sp;
616 auto reg_ctx = thread.GetRegisterContext();
618 return return_valobj_sp;
623 const uint32_t type_flags = compiler_type.
GetTypeInfo();
624 const size_t byte_size =
625 llvm::expectedToOptional(compiler_type.
GetByteSize(&thread)).value_or(0);
626 const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
627 const llvm::Triple::ArchType machine = arch.
GetMachine();
630 if (type_flags & eTypeIsInteger) {
633 return return_valobj_sp;
636 else if (type_flags & eTypeIsPointer) {
639 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
645 else if (type_flags & eTypeIsFloat) {
646 bool is_complex =
false;
649 !(type_flags & eTypeIsVector) && !is_complex) {
650 const uint32_t arch_fp_flags =
653 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
654 return return_valobj_sp;
658 return return_valobj_sp;
663 llvm::Type &type)
const {
667 auto reg_ctx = thread.GetRegisterContext();
669 return return_valobj_sp;
671 uint32_t type_flags = 0;
672 if (type.isIntegerTy())
673 type_flags = eTypeIsInteger;
674 else if (type.isVoidTy())
675 type_flags = eTypeIsPointer;
676 else if (type.isFloatTy())
677 type_flags = eTypeIsFloat;
679 const uint32_t byte_size = type.getPrimitiveSizeInBits() / CHAR_BIT;
680 const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
681 const llvm::Triple::ArchType machine = arch.
GetMachine();
684 if (type_flags & eTypeIsInteger) {
687 return return_valobj_sp;
690 else if (type_flags & eTypeIsPointer) {
693 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
699 else if (type_flags & eTypeIsFloat) {
700 const uint32_t arch_fp_flags =
703 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
704 return return_valobj_sp;
707 return return_valobj_sp;
714 if (!return_compiler_type)
715 return return_valobj_sp;
735 plan_sp->AppendRow(std::move(row));
736 plan_sp->SetSourceName(
"riscv function-entry unwind plan");
760 plan_sp->AppendRow(std::move(row));
761 plan_sp->SetSourceName(
"riscv default unwind plan");
763 plan_sp->SetUnwindPlanValidAtAllInstructions(
eLazyBoolNo);
775 const char *name = reg_info->
name;
777 uint32_t arch_flags = arch.
GetFlags();
782 bool is_callee_saved =
783 llvm::StringSwitch<bool>(name)
785 .Cases({
"ra",
"sp",
"fp"},
true)
786 .Cases({
"s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9"},
788 .Cases({
"s10",
"s11"},
true)
790 .Cases({
"x1",
"x2",
"x8",
"x9",
"x18",
"x19",
"x20",
"x21",
"x22"},
792 .Cases({
"x23",
"x24",
"x25",
"x26",
"x27"},
true)
794 .Cases({
"fs0",
"fs1",
"fs2",
"fs3",
"fs4",
"fs5",
"fs6",
"fs7"},
796 .Cases({
"fs8",
"fs9",
"fs10",
"fs11"}, is_hw_fp)
798 .Cases({
"f8",
"f9",
"f18",
"f19",
"f20",
"f21",
"f22",
"f23"},
800 .Cases({
"f24",
"f25",
"f26",
"f27"}, is_hw_fp)
803 return is_callee_saved;
816 return llvm::StringSwitch<uint32_t>(name)
833 std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) {
836 for (
auto it : llvm::enumerate(regs)) {
838 if (it.value().name ==
"zero")
839 it.value().alt_name.SetCString(
"x0");
840 else if (it.value().name ==
"ra")
841 it.value().alt_name.SetCString(
"x1");
842 else if (it.value().name ==
"sp")
843 it.value().alt_name.SetCString(
"x2");
844 else if (it.value().name ==
"gp")
845 it.value().alt_name.SetCString(
"x3");
846 else if (it.value().name ==
"fp")
847 it.value().alt_name.SetCString(
"s0");
848 else if (it.value().name ==
"tp")
849 it.value().alt_name.SetCString(
"x4");
850 else if (it.value().name ==
"s0")
851 it.value().alt_name.SetCString(
"x8");
852 else if (it.value().name ==
"s1")
853 it.value().alt_name.SetCString(
"x9");
854 else if (it.value().name ==
"t0")
855 it.value().alt_name.SetCString(
"x5");
856 else if (it.value().name ==
"t1")
857 it.value().alt_name.SetCString(
"x6");
858 else if (it.value().name ==
"t2")
859 it.value().alt_name.SetCString(
"x7");
860 else if (it.value().name ==
"a0")
861 it.value().alt_name.SetCString(
"x10");
862 else if (it.value().name ==
"a1")
863 it.value().alt_name.SetCString(
"x11");
864 else if (it.value().name ==
"a2")
865 it.value().alt_name.SetCString(
"x12");
866 else if (it.value().name ==
"a3")
867 it.value().alt_name.SetCString(
"x13");
868 else if (it.value().name ==
"a4")
869 it.value().alt_name.SetCString(
"x14");
870 else if (it.value().name ==
"a5")
871 it.value().alt_name.SetCString(
"x15");
872 else if (it.value().name ==
"a6")
873 it.value().alt_name.SetCString(
"x16");
874 else if (it.value().name ==
"a7")
875 it.value().alt_name.SetCString(
"x17");
876 else if (it.value().name ==
"s2")
877 it.value().alt_name.SetCString(
"x18");
878 else if (it.value().name ==
"s3")
879 it.value().alt_name.SetCString(
"x19");
880 else if (it.value().name ==
"s4")
881 it.value().alt_name.SetCString(
"x20");
882 else if (it.value().name ==
"s5")
883 it.value().alt_name.SetCString(
"x21");
884 else if (it.value().name ==
"s6")
885 it.value().alt_name.SetCString(
"x22");
886 else if (it.value().name ==
"s7")
887 it.value().alt_name.SetCString(
"x23");
888 else if (it.value().name ==
"s8")
889 it.value().alt_name.SetCString(
"x24");
890 else if (it.value().name ==
"s9")
891 it.value().alt_name.SetCString(
"x25");
892 else if (it.value().name ==
"s10")
893 it.value().alt_name.SetCString(
"x26");
894 else if (it.value().name ==
"s11")
895 it.value().alt_name.SetCString(
"x27");
896 else if (it.value().name ==
"t3")
897 it.value().alt_name.SetCString(
"x28");
898 else if (it.value().name ==
"t4")
899 it.value().alt_name.SetCString(
"x29");
900 else if (it.value().name ==
"t5")
901 it.value().alt_name.SetCString(
"x30");
902 else if (it.value().name ==
"t6")
903 it.value().alt_name.SetCString(
"x31");
906 it.value().regnum_generic =
GetGenericNum(it.value().name.GetStringRef());
static const RegisterInfo g_register_infos[]
#define DEFINE_REGISTER_STUB(dwarf_num, str_name)
static const size_t word_size
static size_t TotalArgsSizeInWords(const llvm::ArrayRef< ABI::CallArgument > &args)
#define DEFINE_GENERIC_REGISTER_STUB(dwarf_num, str_name, generic_num)
static const size_t reg_size
static size_t AugmentArgSize(size_t size_in_bytes)
static ValueObjectSP GetValObjFromIntRegs(Thread &thread, const RegisterContextSP ®_ctx, llvm::Triple::ArchType machine, uint32_t type_flags, uint32_t byte_size)
static bool UpdateRegister(RegisterContext *reg_ctx, const lldb::RegisterKind reg_kind, const uint32_t reg_num, const addr_t value)
static void LogInitInfo(Log &log, const Thread &thread, addr_t sp, addr_t func_addr, addr_t return_addr, const llvm::ArrayRef< addr_t > args)
static ValueObjectSP GetValObjFromFPRegs(Thread &thread, const RegisterContextSP ®_ctx, llvm::Triple::ArchType machine, uint32_t type_flags, uint32_t byte_size)
static uint32_t GetGenericNum(llvm::StringRef name)
static constexpr size_t g_regs_for_args_count
static ValueObjectSP GetValObjFromIntRegs(Thread &thread, const RegisterContextSP ®_ctx, llvm::Triple::ArchType machine, uint32_t type_flags, uint32_t byte_size)
static bool UpdateRegister(RegisterContext *reg_ctx, const lldb::RegisterKind reg_kind, const uint32_t reg_num, const addr_t value)
static void LogInitInfo(Log &log, const Thread &thread, addr_t sp, addr_t func_addr, addr_t return_addr, const llvm::ArrayRef< addr_t > args)
static size_t TotalArgsSizeInWords(bool is_rv64, const llvm::ArrayRef< ABI::CallArgument > &args)
static size_t AugmentArgSize(bool is_rv64, size_t size_in_bytes)
static void SetInteger(Scalar &scalar, uint64_t raw_value, bool is_signed)
static uint32_t GetGenericNum(llvm::StringRef name)
static bool SetSizedInteger(Scalar &scalar, uint64_t raw_value, uint8_t size_in_bytes, bool is_signed)
static ValueObjectSP GetValObjFromFPRegs(Thread &thread, const RegisterContextSP ®_ctx, llvm::Triple::ArchType machine, uint32_t arch_fp_flags, uint32_t type_flags, uint32_t byte_size)
static bool SetSizedFloat(Scalar &scalar, uint64_t raw_value, uint8_t size_in_bytes)
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
#define LLDB_PLUGIN_DEFINE_ADV(ClassName, PluginName)
static llvm::StringRef GetPluginNameStatic()
bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info)
void SetIsRV64(bool is_rv64)
lldb::UnwindPlanSP CreateDefaultUnwindPlan() override
void AugmentRegisterInfo(std::vector< lldb_private::DynamicRegisterInfo::Register > ®s) override
lldb::UnwindPlanSP CreateFunctionEntryUnwindPlan() override
lldb_private::Status SetReturnValueObject(lldb::StackFrameSP &frame_sp, lldb::ValueObjectSP &new_value) override
bool PrepareTrivialCall(lldb_private::Thread &thread, lldb::addr_t sp, lldb::addr_t functionAddress, lldb::addr_t returnAddress, llvm::ArrayRef< lldb::addr_t > args) const override
lldb::ValueObjectSP GetReturnValueObjectSimple(lldb_private::Thread &thread, lldb_private::CompilerType &ast_type) const
bool GetArgumentValues(lldb_private::Thread &thread, lldb_private::ValueList &values) const override
static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, const lldb_private::ArchSpec &arch)
bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override
const lldb_private::RegisterInfo * GetRegisterInfoArray(uint32_t &count) override
lldb::ValueObjectSP GetReturnValueObjectImpl(lldb_private::Thread &thread, lldb_private::CompilerType &type) const override
static std::unique_ptr< llvm::MCRegisterInfo > MakeMCRegisterInfo(const ArchSpec &arch)
Utility function to construct a MCRegisterInfo using the ArchSpec triple.
lldb::ProcessSP GetProcessSP() const
Request to get a Process shared pointer.
An architecture specification class.
llvm::Triple & GetTriple()
Architecture triple accessor.
uint32_t GetFlags() const
llvm::Triple::ArchType GetMachine() const
Returns a machine family for the current architecture.
@ eRISCV_float_abi_double
single precision floating point, +f
@ eRISCV_float_abi_soft
RVC, +c.
@ eRISCV_float_abi_quad
double precision floating point, +d
@ eRISCV_float_abi_mask
quad precision floating point, +q
@ eRISCV_float_abi_single
soft float
Generic representation of a type in a programming language.
llvm::Expected< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
bool IsIntegerOrEnumerationType(bool &is_signed) const
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
bool IsFloatingPointType(bool &is_complex) const
bool IsPointerType(CompilerType *pointee_type=nullptr) const
A uniqued constant string class.
A subclass of DataBuffer that stores a data buffer on the heap.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
void PutString(llvm::StringRef str)
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
void AugmentRegisterInfo(std::vector< DynamicRegisterInfo::Register > ®s) override
const RegisterInfo * GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num)
bool WriteRegisterFromUnsigned(uint32_t reg, uint64_t uval)
uint32_t GetAsMemoryData(const RegisterInfo ®_info, void *dst, uint32_t dst_len, lldb::ByteOrder dst_byte_order, Status &error) const
static Status FromErrorStringWithFormat(const char *format,...) __attribute__((format(printf
static Status FromErrorString(const char *str)
bool Fail() const
Test for error condition.
const char * AsCString(const char *default_error_str="unknown error") const
Get the error string associated with the current error.
virtual lldb::RegisterContextSP GetRegisterContext()=0
lldb::ProcessSP GetProcess() const
void SetIsRegisterPlusOffset(uint32_t reg_num, int32_t offset)
bool SetRegisterLocationToAtCFAPlusOffset(uint32_t reg_num, int32_t offset, bool can_replace)
const FAValue & GetCFAValue() const
bool SetRegisterLocationToRegister(uint32_t reg_num, uint32_t other_reg_num, bool can_replace)
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size, lldb::addr_t address=LLDB_INVALID_ADDRESS)
const Scalar & GetScalar() const
See comment on m_scalar to understand what GetScalar returns.
@ Scalar
A raw scalar value.
void SetCompilerType(const CompilerType &compiler_type)
void SetValueType(ValueType value_type)
void SetBytes(const void *bytes, int len)
#define LLDB_REGNUM_GENERIC_RA
#define LLDB_REGNUM_GENERIC_ARG8
#define LLDB_REGNUM_GENERIC_ARG6
#define LLDB_REGNUM_GENERIC_SP
#define LLDB_REGNUM_GENERIC_ARG4
#define LLDB_REGNUM_GENERIC_ARG3
#define LLDB_REGNUM_GENERIC_ARG1
#define LLDB_REGNUM_GENERIC_ARG7
#define LLDB_INVALID_REGNUM
#define LLDB_REGNUM_GENERIC_ARG2
#define LLDB_REGNUM_GENERIC_PC
#define LLDB_REGNUM_GENERIC_FP
#define LLDB_REGNUM_GENERIC_ARG5
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
std::shared_ptr< lldb_private::ABI > ABISP
std::shared_ptr< lldb_private::StackFrame > StackFrameSP
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
std::shared_ptr< lldb_private::Process > ProcessSP
ByteOrder
Byte ordering definitions.
std::shared_ptr< lldb_private::UnwindPlan > UnwindPlanSP
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
RegisterKind
Register numbering types.
@ eRegisterKindGeneric
insn ptr reg, stack ptr reg, etc not specific to any particular target
@ eRegisterKindDWARF
the register numbers seen DWARF
Every register is described in detail including its name, alternate name (optional),...
const char * name
Name of this register, can't be NULL.