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

Reply via email to