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 uint32_t float_count = 0;
647 bool is_complex =
false;
650 float_count == 1 && !is_complex) {
651 const uint32_t arch_fp_flags =
654 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
655 return return_valobj_sp;
659 return return_valobj_sp;
664 llvm::Type &type)
const {
668 auto reg_ctx = thread.GetRegisterContext();
670 return return_valobj_sp;
672 uint32_t type_flags = 0;
673 if (type.isIntegerTy())
674 type_flags = eTypeIsInteger;
675 else if (type.isVoidTy())
676 type_flags = eTypeIsPointer;
677 else if (type.isFloatTy())
678 type_flags = eTypeIsFloat;
680 const uint32_t byte_size = type.getPrimitiveSizeInBits() / CHAR_BIT;
681 const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
682 const llvm::Triple::ArchType machine = arch.
GetMachine();
685 if (type_flags & eTypeIsInteger) {
688 return return_valobj_sp;
691 else if (type_flags & eTypeIsPointer) {
694 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
700 else if (type_flags & eTypeIsFloat) {
701 const uint32_t arch_fp_flags =
704 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
705 return return_valobj_sp;
708 return return_valobj_sp;
715 if (!return_compiler_type)
716 return return_valobj_sp;
736 plan_sp->AppendRow(std::move(row));
737 plan_sp->SetSourceName(
"riscv function-entry unwind plan");
761 plan_sp->AppendRow(std::move(row));
762 plan_sp->SetSourceName(
"riscv default unwind plan");
764 plan_sp->SetUnwindPlanValidAtAllInstructions(
eLazyBoolNo);
776 const char *name = reg_info->
name;
778 uint32_t arch_flags = arch.
GetFlags();
783 bool is_callee_saved =
784 llvm::StringSwitch<bool>(name)
786 .Cases(
"ra",
"sp",
"fp",
true)
787 .Cases(
"s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9",
789 .Cases(
"s10",
"s11",
true)
791 .Cases(
"x1",
"x2",
"x8",
"x9",
"x18",
"x19",
"x20",
"x21",
"x22",
793 .Cases(
"x23",
"x24",
"x25",
"x26",
"x27",
true)
795 .Cases(
"fs0",
"fs1",
"fs2",
"fs3",
"fs4",
"fs5",
"fs6",
"fs7",
797 .Cases(
"fs8",
"fs9",
"fs10",
"fs11", is_hw_fp)
799 .Cases(
"f8",
"f9",
"f18",
"f19",
"f20",
"f21",
"f22",
"f23", is_hw_fp)
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 IsFloatingPointType(uint32_t &count, bool &is_complex) const
bool IsIntegerOrEnumerationType(bool &is_signed) const
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) 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.