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)
195 count = dwarf::g_register_infos.size();
196 return dwarf::g_register_infos.data();
205 llvm::Triple::ArchType machine = arch.
GetTriple().getArch();
207 if (llvm::Triple::riscv32 != machine && llvm::Triple::riscv64 != machine)
213 abi->
SetIsRV64((llvm::Triple::riscv64 == machine) ?
true :
false);
219 return llvm::alignTo(size_in_bytes,
word_size);
224 const llvm::ArrayRef<ABI::CallArgument> &args) {
227 size_t total_size = 0;
228 for (
const auto &arg : args)
240 const uint32_t reg_num,
const addr_t value) {
246 static_cast<uint64_t
>(value));
256 const llvm::ArrayRef<addr_t> args) {
257 std::stringstream ss;
258 ss <<
"ABISysV_riscv::PrepareTrivialCall"
259 <<
" (tid = 0x" << std::hex << thread.GetID() <<
", sp = 0x" <<
sp
260 <<
", func_addr = 0x" << func_addr <<
", return_addr = 0x" << return_addr;
262 for (
auto [idx, arg] : enumerate(args))
263 ss <<
", arg" << std::dec << idx <<
" = 0x" << std::hex << arg;
270 llvm::ArrayRef<addr_t> args)
const {
271 Log *log =
GetLog(LLDBLog::Expressions);
277 LLDB_LOG(log,
"Failed to get RegisterContext");
282 LLDB_LOG(log,
"Function has {0} arguments, but only {1} are allowed!",
288 for (
auto [idx, arg] : enumerate(args)) {
289 const RegisterInfo *reg_info = reg_ctx_sp->GetRegisterInfo(
291 LLDB_LOG(log,
"About to write arg{0} ({1:x}) into {2}", idx, arg,
294 if (!reg_ctx_sp->WriteRegisterFromUnsigned(reg_info, arg)) {
295 LLDB_LOG(log,
"Failed to write arg{0} ({1:x}) into {2}", idx, arg,
311 LLDB_LOG(log,
"ABISysV_riscv::{0}() success", __FUNCTION__);
317 llvm::ArrayRef<ABI::CallArgument> args)
const {
322 uint32_t pc_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
327 uint32_t ra_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
332 uint32_t sp_reg = reg_ctx->ConvertRegisterKindToRegisterNumber(
345 for (
const auto &arg : args) {
353 if (process->WriteMemory(
sp, arg.data_up.get(), arg.size,
error) <
359 *
const_cast<addr_t *
>(&arg.value) =
sp;
363 assert(prototype.getFunctionNumParams() == args.size());
365 const size_t num_args = args.size();
366 const size_t num_args_in_regs =
376 uint8_t reg_value[8];
379 for (
size_t i = 0; i < args_size; ++i) {
380 auto value =
reinterpret_cast<const uint8_t *
>(&args[i].value);
385 if (i < num_args_in_regs) {
388 memcpy(reg_value, value, end);
390 memset(reg_value + end, 0,
reg_size - end);
392 RegisterValue reg_val_obj(llvm::ArrayRef(reg_value,
reg_size),
394 if (!reg_ctx->WriteRegister(
408 if (process->WriteMemory(
sp - offset, value, size,
error) < size ||
419 reg_ctx->WriteRegisterFromUnsigned(pc_reg,
pc);
420 reg_ctx->WriteRegisterFromUnsigned(ra_reg,
ra);
421 reg_ctx->WriteRegisterFromUnsigned(sp_reg,
sp);
439 CompilerType compiler_type = new_value_sp->GetCompilerType();
440 if (!compiler_type) {
445 auto ®_ctx = *frame_sp->GetThread()->GetRegisterContext();
447 bool is_signed =
false;
451 "We don't support returning other types at present");
456 size_t num_bytes = new_value_sp->GetData(data, result);
460 "Couldn't convert return value to raw data: %s", result.
AsCString());
467 uint64_t raw_value = data.
GetMaxU64(&offset, num_bytes);
471 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
473 "Couldn't write value to register %s", reg_info->
name);
488 if (!reg_ctx.WriteRegisterFromUnsigned(reg_info, raw_value)) {
490 "Couldn't write value to register %s", reg_info->
name);
497 "We don't support returning large integer values at present.");
503 raw_value &= std::numeric_limits<T>::max();
505 scalar =
static_cast<typename std::make_signed<T>::type
>(raw_value);
507 scalar =
static_cast<T
>(raw_value);
511 uint8_t size_in_bytes,
bool is_signed) {
512 switch (size_in_bytes) {
516 case sizeof(uint64_t):
520 case sizeof(uint32_t):
524 case sizeof(uint16_t):
528 case sizeof(uint8_t):
537 uint8_t size_in_bytes) {
538 switch (size_in_bytes) {
542 case sizeof(uint64_t):
543 scalar = *
reinterpret_cast<double *
>(&raw_value);
546 case sizeof(uint32_t):
547 scalar = *
reinterpret_cast<float *
>(&raw_value);
556 llvm::Triple::ArchType machine,
558 uint32_t byte_size) {
568 case sizeof(uint32_t):
570 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
572 case sizeof(uint64_t):
574 if (llvm::Triple::riscv32 == machine) {
575 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0) &
UINT32_MAX;
577 (reg_ctx->ReadRegisterAsUnsigned(reg_info_a1, 0) &
UINT32_MAX) << 32U;
579 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
584 if (llvm::Triple::riscv32 == machine)
585 return return_valobj_sp;
588 std::unique_ptr<DataBufferHeap> heap_data_up(
590 const ByteOrder byte_order = thread.GetProcess()->GetByteOrder();
592 if (reg_ctx->ReadRegister(reg_info_a0, reg_value_a0) &&
593 reg_ctx->ReadRegister(reg_info_a1, reg_value_a1)) {
596 heap_data_up->GetBytes() + 0, 8,
597 byte_order,
error) &&
599 heap_data_up->GetBytes() + 8, 8,
600 byte_order,
error)) {
601 value.
SetBytes(heap_data_up.release(), byte_size);
603 thread.GetStackFrameAtIndex(0).get(), value,
ConstString(
""));
609 return return_valobj_sp;
612 if (type_flags & eTypeIsInteger) {
613 const bool is_signed = (type_flags & eTypeIsSigned) != 0;
615 return return_valobj_sp;
616 }
else if (type_flags & eTypeIsFloat) {
618 return return_valobj_sp;
620 return return_valobj_sp;
624 thread.GetStackFrameAtIndex(0).get(), value,
ConstString(
""));
625 return return_valobj_sp;
630 llvm::Triple::ArchType machine, uint32_t arch_fp_flags,
631 uint32_t type_flags, uint32_t byte_size) {
632 auto reg_info_fa0 = reg_ctx->GetRegisterInfoByName(
"fa0");
633 bool use_fp_regs =
false;
636 switch (arch_fp_flags) {
641 return return_valobj_sp;
661 raw_value = reg_ctx->ReadRegisterAsUnsigned(reg_info_fa0, 0);
663 return return_valobj_sp;
678 return return_valobj_sp;
680 auto reg_ctx = thread.GetRegisterContext();
682 return return_valobj_sp;
687 const uint32_t type_flags = compiler_type.
GetTypeInfo();
688 const size_t byte_size =
689 llvm::expectedToOptional(compiler_type.
GetByteSize(&thread)).value_or(0);
690 const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
691 const llvm::Triple::ArchType machine = arch.
GetMachine();
694 if (type_flags & eTypeIsInteger) {
697 return return_valobj_sp;
700 else if (type_flags & eTypeIsPointer) {
703 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
710 const uint32_t arch_fp_flags =
713 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
714 return return_valobj_sp;
718 return return_valobj_sp;
723 llvm::Type &type)
const {
727 auto reg_ctx = thread.GetRegisterContext();
729 return return_valobj_sp;
731 uint32_t type_flags = 0;
732 if (type.isIntegerTy())
733 type_flags = eTypeIsInteger;
734 else if (type.isVoidTy())
735 type_flags = eTypeIsPointer;
736 else if (type.isFloatTy())
737 type_flags = eTypeIsFloat;
739 const uint32_t byte_size = type.getPrimitiveSizeInBits() / CHAR_BIT;
740 const ArchSpec arch = thread.GetProcess()->GetTarget().GetArchitecture();
741 const llvm::Triple::ArchType machine = arch.
GetMachine();
744 if (type_flags & eTypeIsInteger) {
747 return return_valobj_sp;
750 else if (type_flags & eTypeIsPointer) {
753 value.
GetScalar() = reg_ctx->ReadRegisterAsUnsigned(reg_info_a0, 0);
759 else if (type_flags & eTypeIsFloat) {
760 const uint32_t arch_fp_flags =
763 thread, reg_ctx, machine, arch_fp_flags, type_flags, byte_size);
764 return return_valobj_sp;
767 return return_valobj_sp;
774 if (!return_compiler_type)
775 return return_valobj_sp;
795 plan_sp->AppendRow(std::move(row));
796 plan_sp->SetSourceName(
"riscv function-entry unwind plan");
823 plan_sp->AppendRow(std::move(row));
824 plan_sp->SetSourceName(
"riscv default unwind plan");
826 plan_sp->SetUnwindPlanValidAtAllInstructions(
eLazyBoolNo);
840 const char *name = reg_info->
name;
842 uint32_t arch_flags = arch.
GetFlags();
847 bool is_callee_saved =
848 llvm::StringSwitch<bool>(name)
850 .Cases({
"ra",
"sp",
"fp"},
true)
851 .Cases({
"s0",
"s1",
"s2",
"s3",
"s4",
"s5",
"s6",
"s7",
"s8",
"s9"},
853 .Cases({
"s10",
"s11"},
true)
855 .Cases({
"x1",
"x2",
"x8",
"x9",
"x18",
"x19",
"x20",
"x21",
"x22"},
857 .Cases({
"x23",
"x24",
"x25",
"x26",
"x27"},
true)
859 .Cases({
"fs0",
"fs1",
"fs2",
"fs3",
"fs4",
"fs5",
"fs6",
"fs7"},
861 .Cases({
"fs8",
"fs9",
"fs10",
"fs11"}, is_hw_fp)
863 .Cases({
"f8",
"f9",
"f18",
"f19",
"f20",
"f21",
"f22",
"f23"},
865 .Cases({
"f24",
"f25",
"f26",
"f27"}, is_hw_fp)
870 return is_callee_saved;
883 return llvm::StringSwitch<uint32_t>(name)
901 std::vector<lldb_private::DynamicRegisterInfo::Register> ®s) {
904 for (
auto it : llvm::enumerate(regs)) {
906 if (it.value().name ==
"zero")
907 it.value().alt_name.SetCString(
"x0");
908 else if (it.value().name ==
"ra")
909 it.value().alt_name.SetCString(
"x1");
910 else if (it.value().name ==
"sp")
911 it.value().alt_name.SetCString(
"x2");
912 else if (it.value().name ==
"gp")
913 it.value().alt_name.SetCString(
"x3");
914 else if (it.value().name ==
"fp") {
915 it.value().name.SetCString(
"s0");
916 it.value().alt_name.SetCString(
"x8");
917 }
else if (it.value().name ==
"tp")
918 it.value().alt_name.SetCString(
"x4");
919 else if (it.value().name ==
"s0")
920 it.value().alt_name.SetCString(
"x8");
921 else if (it.value().name ==
"s1")
922 it.value().alt_name.SetCString(
"x9");
923 else if (it.value().name ==
"t0")
924 it.value().alt_name.SetCString(
"x5");
925 else if (it.value().name ==
"t1")
926 it.value().alt_name.SetCString(
"x6");
927 else if (it.value().name ==
"t2")
928 it.value().alt_name.SetCString(
"x7");
929 else if (it.value().name ==
"a0")
930 it.value().alt_name.SetCString(
"x10");
931 else if (it.value().name ==
"a1")
932 it.value().alt_name.SetCString(
"x11");
933 else if (it.value().name ==
"a2")
934 it.value().alt_name.SetCString(
"x12");
935 else if (it.value().name ==
"a3")
936 it.value().alt_name.SetCString(
"x13");
937 else if (it.value().name ==
"a4")
938 it.value().alt_name.SetCString(
"x14");
939 else if (it.value().name ==
"a5")
940 it.value().alt_name.SetCString(
"x15");
941 else if (it.value().name ==
"a6")
942 it.value().alt_name.SetCString(
"x16");
943 else if (it.value().name ==
"a7")
944 it.value().alt_name.SetCString(
"x17");
945 else if (it.value().name ==
"s2")
946 it.value().alt_name.SetCString(
"x18");
947 else if (it.value().name ==
"s3")
948 it.value().alt_name.SetCString(
"x19");
949 else if (it.value().name ==
"s4")
950 it.value().alt_name.SetCString(
"x20");
951 else if (it.value().name ==
"s5")
952 it.value().alt_name.SetCString(
"x21");
953 else if (it.value().name ==
"s6")
954 it.value().alt_name.SetCString(
"x22");
955 else if (it.value().name ==
"s7")
956 it.value().alt_name.SetCString(
"x23");
957 else if (it.value().name ==
"s8")
958 it.value().alt_name.SetCString(
"x24");
959 else if (it.value().name ==
"s9")
960 it.value().alt_name.SetCString(
"x25");
961 else if (it.value().name ==
"s10")
962 it.value().alt_name.SetCString(
"x26");
963 else if (it.value().name ==
"s11")
964 it.value().alt_name.SetCString(
"x27");
965 else if (it.value().name ==
"t3")
966 it.value().alt_name.SetCString(
"x28");
967 else if (it.value().name ==
"t4")
968 it.value().alt_name.SetCString(
"x29");
969 else if (it.value().name ==
"t5")
970 it.value().alt_name.SetCString(
"x30");
971 else if (it.value().name ==
"t6")
972 it.value().alt_name.SetCString(
"x31");
975 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 IsRealFloatingPointType() const
Returns true for non-complex float types.
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)
void SetUnspecifiedRegistersAreUndefined(bool unspec_is_undef)
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, uint32_t addr_byte_size, lldb::addr_t address=LLDB_INVALID_ADDRESS, ValueObjectManager *manager=nullptr)
These routines create ValueObjectConstResult ValueObjects from various data sources.
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_TP
#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.