kasper81 created this revision. kasper81 added reviewers: DavidSpickett, Emmmer, tzb99. kasper81 added a project: LLDB. Herald added subscribers: sunshaoce, VincentWu, luke957, vkmr, frasercrmck, evandro, luismarques, apazos, sameer.abuasal, JDevlieghere, s.egerton, Jim, benna, psnobl, jocewei, PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, jrtc27, shiva0217, kito-cheng, niosHD, sabuasal, simoncook, johnrusso, rbar, asb, arichardson, mgorny. Herald added a project: All. kasper81 requested review of this revision. Herald added subscribers: lldb-commits, pcwang-thead, eopXD, MaskRay.
Supersedes https://reviews.llvm.org/D62732, since author is not working on it anymore (https://reviews.llvm.org/D62732?vs=on&id=341471#3561717). This is to get the basic stuff working with DefaultUnwindPlan. We can incrementally add more plans in the future and make the implementation more robust. | Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D132510 Files: lldb/source/Plugins/ABI/CMakeLists.txt lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h lldb/source/Plugins/ABI/RISCV/CMakeLists.txt lldb/source/Target/Platform.cpp
Index: lldb/source/Target/Platform.cpp =================================================================== --- lldb/source/Target/Platform.cpp +++ lldb/source/Target/Platform.cpp @@ -1928,10 +1928,17 @@ case llvm::Triple::riscv32: case llvm::Triple::riscv64: { + static const uint8_t g_riscv_c_opcode[] = {0x02, 0x90}; // c_ebreak static const uint8_t g_riscv_opcode[] = {0x73, 0x00, 0x10, 0x00}; // ebreak - trap_opcode = g_riscv_opcode; - trap_opcode_size = sizeof(g_riscv_opcode); - } break; + if (arch.GetFlags() & ArchSpec::eRISCV_rvc) { + trap_opcode = g_riscv_c_opcode; + trap_opcode_size = sizeof(g_riscv_c_opcode); + } else { + trap_opcode = g_riscv_opcode; + trap_opcode_size = sizeof(g_riscv_opcode); + } + break; + } default: return 0; Index: lldb/source/Plugins/ABI/RISCV/CMakeLists.txt =================================================================== --- /dev/null +++ lldb/source/Plugins/ABI/RISCV/CMakeLists.txt @@ -0,0 +1,10 @@ +add_lldb_library(lldbPluginABISysV_riscv PLUGIN + ABISysV_riscv.cpp + + LINK_LIBS + lldbCore + lldbSymbol + lldbTarget + LINK_COMPONENTS + Support +) Index: lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h =================================================================== --- /dev/null +++ lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.h @@ -0,0 +1,119 @@ +//===-- ABISysV_riscv.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_ABI_RISCV_ABISYSV_RISCV_H +#define LLDB_SOURCE_PLUGINS_ABI_RISCV_ABISYSV_RISCV_H + +#include "lldb/Target/ABI.h" +#include "lldb/lldb-private.h" + +class ABISysV_riscv : public lldb_private::MCBasedABI { + bool isRV64; + +public: + ~ABISysV_riscv() override = default; + + size_t GetRedZoneSize() const override { return 0; } + + 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 { + // TODO: Implement + return false; + } + + bool GetArgumentValues(lldb_private::Thread &thread, + lldb_private::ValueList &values) const override { + // TODO: Implement + return false; + } + + lldb_private::Status + SetReturnValueObject(lldb::StackFrameSP &frame_sp, + lldb::ValueObjectSP &new_value) override { + // TODO: Implement + lldb_private::Status error; + error.SetErrorString("Not yet implemented"); + return error; + } + + lldb::ValueObjectSP + GetReturnValueObjectImpl(lldb_private::Thread &thread, + lldb_private::CompilerType &type) const override { + // TODO: Implement + lldb::ValueObjectSP return_valobj; + return return_valobj; + } + + bool + CreateFunctionEntryUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool CreateDefaultUnwindPlan(lldb_private::UnwindPlan &unwind_plan) override; + + bool RegisterIsVolatile(const lldb_private::RegisterInfo *reg_info) override; + + bool CallFrameAddressIsValid(lldb::addr_t cfa) override { + // Assume any address except zero is valid + if (cfa == 0) + return false; + return true; + } + + bool CodeAddressIsValid(lldb::addr_t pc) override { + // Ensure addresses are smaller than XLEN bits wide. Calls can use the least + // significant bit to store auxiliary information, so no strict check is + // done for alignment. + if (!isRV64) + return (pc <= UINT32_MAX); + return (pc <= UINT64_MAX); + } + + lldb::addr_t FixCodeAddress(lldb::addr_t pc) override { + // Since the least significant bit of a code address can be used to store + // auxiliary information, that bit must be zeroed in any addresses. + return pc & ~(lldb::addr_t)1; + } + + // Static Functions + + static void Initialize(); + + static void Terminate(); + + static lldb::ABISP CreateInstance(lldb::ProcessSP process_sp, + const lldb_private::ArchSpec &arch); + + // PluginInterface protocol + + static lldb_private::ConstString GetPluginNameStatic(); + + lldb_private::ConstString GetPluginName() override; + + uint32_t GetPluginVersion() override { return 1; } + +protected: + bool RegisterIsCalleeSaved(const lldb_private::RegisterInfo *reg_info); + + std::pair<uint32_t, uint32_t> + GetEHAndDWARFNums(llvm::StringRef name) override; + + uint32_t GetGenericNum(llvm::StringRef reg) override; + + bool IsHardFloatProcess() const; + +private: + ABISysV_riscv(lldb::ProcessSP process_sp, + std::unique_ptr<llvm::MCRegisterInfo> info_up, bool _isRV64) + : lldb_private::MCBasedABI(std::move(process_sp), std::move(info_up)), + isRV64(_isRV64) { + // Call CreateInstance instead. + } +}; + +#endif // LLDB_SOURCE_PLUGINS_ABI_RISCV_ABISYSV_RISCV_H Index: lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp =================================================================== --- /dev/null +++ lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp @@ -0,0 +1,243 @@ +//===-- ABISysV_riscv.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 "ABISysV_riscv.h" + +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/StringSwitch.h" +#include "llvm/ADT/Triple.h" + +#include "lldb/Core/Module.h" +#include "lldb/Core/PluginManager.h" +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Core/ValueObjectMemory.h" +#include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/Utility/Status.h" + +using namespace lldb; +using namespace lldb_private; + +LLDB_PLUGIN_DEFINE(ABISysV_riscv) + +enum riscv_dwarf_regnums { + dwarf_x0 = 0, + dwarf_x1, + dwarf_x2, + dwarf_x3, + dwarf_x4, + dwarf_x5, + dwarf_x6, + dwarf_x7, + dwarf_x8, + dwarf_x9, + dwarf_x10, + dwarf_x11, + dwarf_x12, + dwarf_x13, + dwarf_x14, + dwarf_x15, + dwarf_x16, + dwarf_x17, + dwarf_x18, + dwarf_x19, + dwarf_x20, + dwarf_x21, + dwarf_x22, + dwarf_x23, + dwarf_x24, + dwarf_x25, + dwarf_x26, + dwarf_x27, + dwarf_x28, + dwarf_x29, + dwarf_x30, + dwarf_x31, + dwarf_f0 = 32, + dwarf_f1, + dwarf_f2, + dwarf_f3, + dwarf_f4, + dwarf_f5, + dwarf_f6, + dwarf_f7, + dwarf_f8, + dwarf_f9, + dwarf_f10, + dwarf_f11, + dwarf_f12, + dwarf_f13, + dwarf_f14, + dwarf_f15, + dwarf_f16, + dwarf_f17, + dwarf_f18, + dwarf_f19, + dwarf_f20, + dwarf_f21, + dwarf_f22, + dwarf_f23, + dwarf_f24, + dwarf_f25, + dwarf_f26, + dwarf_f27, + dwarf_f28, + dwarf_f29, + dwarf_f30, + dwarf_f31 +}; + +bool ABISysV_riscv::CreateFunctionEntryUnwindPlan(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindGeneric); + + uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC; + uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP; + uint32_t ra_reg_num = LLDB_REGNUM_GENERIC_RA; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Define CFA as the stack pointer + row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0); + + // Previous frame's pc is in ra + row->SetRegisterLocationToRegister(pc_reg_num, ra_reg_num, true); + + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("riscv function-entry unwind plan"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + return true; +} + +bool ABISysV_riscv::CreateDefaultUnwindPlan(UnwindPlan &unwind_plan) { + unwind_plan.Clear(); + unwind_plan.SetRegisterKind(eRegisterKindGeneric); + + uint32_t pc_reg_num = LLDB_REGNUM_GENERIC_PC; + uint32_t sp_reg_num = LLDB_REGNUM_GENERIC_SP; + uint32_t ra_reg_num = LLDB_REGNUM_GENERIC_RA; + + UnwindPlan::RowSP row(new UnwindPlan::Row); + + // Define the CFA as the current stack pointer. + row->GetCFAValue().SetIsRegisterPlusOffset(sp_reg_num, 0); + row->SetOffset(0); + + // The previous frame's pc is stored in ra. + row->SetRegisterLocationToRegister(pc_reg_num, ra_reg_num, true); + + unwind_plan.AppendRow(row); + unwind_plan.SetSourceName("riscv default unwind plan"); + unwind_plan.SetSourcedFromCompiler(eLazyBoolNo); + unwind_plan.SetUnwindPlanValidAtAllInstructions(eLazyBoolNo); + return true; +} + +bool ABISysV_riscv::RegisterIsVolatile( + const lldb_private::RegisterInfo *reg_info) { + return !RegisterIsCalleeSaved(reg_info); +} + +// See "Register Convention" in the RISC-V psABI documentation, which is +// maintained at https://github.com/riscv/riscv-elf-psabi-doc +bool ABISysV_riscv::RegisterIsCalleeSaved( + const lldb_private::RegisterInfo *reg_info) { + if (!reg_info) + return false; + + bool IsCalleeSaved = + llvm::StringSwitch<bool>(reg_info->name) + .Cases("x1", "x2", "x8", "x9", "x18", "x19", "x20", "x21", true) + .Cases("x22", "x23", "x24", "x25", "x26", "x27", true) + .Cases("f8", "f9", "f18", "f19", "f20", "f21", IsHardFloatProcess()) + .Cases("f22", "f23", "f24", "f25", "f26", "f27", IsHardFloatProcess()) + .Default(false); + return IsCalleeSaved; +} + +std::pair<uint32_t, uint32_t> +ABISysV_riscv::GetEHAndDWARFNums(llvm::StringRef name) { + if (name == "ra") + return {LLDB_INVALID_REGNUM, riscv_dwarf_regnums::dwarf_x1}; + if (name == "sp") + return {LLDB_INVALID_REGNUM, riscv_dwarf_regnums::dwarf_x2}; + if (name == "fp") + return {LLDB_INVALID_REGNUM, riscv_dwarf_regnums::dwarf_x8}; + return MCBasedABI::GetEHAndDWARFNums(name); +} + +uint32_t ABISysV_riscv::GetGenericNum(llvm::StringRef name) { + return llvm::StringSwitch<uint32_t>(name) + .Case("pc", LLDB_REGNUM_GENERIC_PC) + .Case("ra", LLDB_REGNUM_GENERIC_RA) + .Case("sp", LLDB_REGNUM_GENERIC_SP) + .Case("fp", LLDB_REGNUM_GENERIC_FP) + .Case("a0", LLDB_REGNUM_GENERIC_ARG1) + .Case("a1", LLDB_REGNUM_GENERIC_ARG2) + .Case("a2", LLDB_REGNUM_GENERIC_ARG3) + .Case("a3", LLDB_REGNUM_GENERIC_ARG4) + .Case("a4", LLDB_REGNUM_GENERIC_ARG5) + .Case("a5", LLDB_REGNUM_GENERIC_ARG6) + .Case("a6", LLDB_REGNUM_GENERIC_ARG7) + .Case("a7", LLDB_REGNUM_GENERIC_ARG8) + .Default(LLDB_INVALID_REGNUM); +} + +bool ABISysV_riscv::IsHardFloatProcess() const { + bool is_hardfloat = false; + ProcessSP process_sp(GetProcessSP()); + if (process_sp) { + const ArchSpec &arch(process_sp->GetTarget().GetArchitecture()); + if (arch.GetFlags() & ArchSpec::eRISCV_float_abi_single || + arch.GetFlags() & ArchSpec::eRISCV_float_abi_double) + is_hardfloat = true; + } + return is_hardfloat; +} + +ABISP +ABISysV_riscv::CreateInstance(lldb::ProcessSP process_sp, + const ArchSpec &arch) { + if (arch.GetTriple().getArch() == llvm::Triple::riscv32 || + arch.GetTriple().getArch() == llvm::Triple::riscv64) { + return ABISP( + new ABISysV_riscv(std::move(process_sp), MakeMCRegisterInfo(arch), + arch.GetTriple().getArch() == llvm::Triple::riscv64)); + } + return ABISP(); +} + +void ABISysV_riscv::Initialize() { + PluginManager::RegisterPlugin( + GetPluginNameStatic(), "System V ABI for riscv targets", CreateInstance); +} + +void ABISysV_riscv::Terminate() { + PluginManager::UnregisterPlugin(CreateInstance); +} + +// PluginInterface protocol + +lldb_private::ConstString ABISysV_riscv::GetPluginNameStatic() { + static ConstString g_name("sysv-riscv"); + return g_name; +} + +lldb_private::ConstString ABISysV_riscv::GetPluginName() { + return GetPluginNameStatic(); +} Index: lldb/source/Plugins/ABI/CMakeLists.txt =================================================================== --- lldb/source/Plugins/ABI/CMakeLists.txt +++ lldb/source/Plugins/ABI/CMakeLists.txt @@ -1,4 +1,4 @@ -foreach(target AArch64 ARM ARC Hexagon Mips PowerPC SystemZ X86) +foreach(target AArch64 ARM ARC Hexagon Mips PowerPC RISCV SystemZ X86) if (${target} IN_LIST LLVM_TARGETS_TO_BUILD) add_subdirectory(${target}) endif()
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits