[llvm-branch-commits] [lldb] 91c701d - [lldb][RISCV] Implement trap handler unwind plan (#166531)

Cullen Rhodes via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Tue Jan 13 02:21:13 PST 2026


Author: Georgiy Samoylov
Date: 2026-01-13T10:18:55Z
New Revision: 91c701df9241ebe212d3bb1a80656492febf56a7

URL: https://github.com/llvm/llvm-project/commit/91c701df9241ebe212d3bb1a80656492febf56a7
DIFF: https://github.com/llvm/llvm-project/commit/91c701df9241ebe212d3bb1a80656492febf56a7.diff

LOG: [lldb][RISCV] Implement trap handler unwind plan (#166531)

This patch introduces special unwind plan for trap handling for RISC-V
and fixes `TestHandleAbort`

Added: 
    

Modified: 
    lldb/include/lldb/Target/Platform.h
    lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp
    lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp
    lldb/source/Plugins/Platform/AIX/PlatformAIX.h
    lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
    lldb/source/Plugins/Platform/Linux/PlatformLinux.h
    lldb/source/Target/RegisterContextUnwind.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index 1104722f52c70..70829c04f5e5b 100644
--- a/lldb/include/lldb/Target/Platform.h
+++ b/lldb/include/lldb/Target/Platform.h
@@ -778,8 +778,8 @@ class Platform : public PluginInterface {
   /// Try to get a specific unwind plan for a named trap handler.
   /// The default is not to have specific unwind plans for trap handlers.
   ///
-  /// \param[in] triple
-  ///     Triple of the current target.
+  /// \param[in] arch
+  ///     Architecture of the current target.
   ///
   /// \param[in] name
   ///     Name of the trap handler function.
@@ -788,8 +788,8 @@ class Platform : public PluginInterface {
   ///     A specific unwind plan for that trap handler, or an empty
   ///     shared pointer. The latter means there is no specific plan,
   ///     unwind as normal.
-  virtual lldb::UnwindPlanSP
-  GetTrapHandlerUnwindPlan(const llvm::Triple &triple, ConstString name) {
+  virtual lldb::UnwindPlanSP GetTrapHandlerUnwindPlan(const ArchSpec &arch,
+                                                      ConstString name) {
     return {};
   }
 

diff  --git a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp
index a5547a4699ca9..d209980d65589 100644
--- a/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp
+++ b/lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp
@@ -735,6 +735,8 @@ UnwindPlanSP ABISysV_riscv::CreateFunctionEntryUnwindPlan() {
   plan_sp->AppendRow(std::move(row));
   plan_sp->SetSourceName("riscv function-entry unwind plan");
   plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
+  plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
+
   return plan_sp;
 }
 
@@ -761,6 +763,8 @@ UnwindPlanSP ABISysV_riscv::CreateDefaultUnwindPlan() {
   plan_sp->SetSourceName("riscv default unwind plan");
   plan_sp->SetSourcedFromCompiler(eLazyBoolNo);
   plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
+  plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolNo);
+
   return plan_sp;
 }
 

diff  --git a/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp
index 21724d83133e9..2122d5d08cb1b 100644
--- a/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp
+++ b/lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp
@@ -132,9 +132,8 @@ void PlatformAIX::GetStatus(Stream &strm) {
 
 void PlatformAIX::CalculateTrapHandlerSymbolNames() {}
 
-lldb::UnwindPlanSP
-PlatformAIX::GetTrapHandlerUnwindPlan(const llvm::Triple &triple,
-                                      ConstString name) {
+lldb::UnwindPlanSP PlatformAIX::GetTrapHandlerUnwindPlan(const ArchSpec &arch,
+                                                         ConstString name) {
   return {};
 }
 

diff  --git a/lldb/source/Plugins/Platform/AIX/PlatformAIX.h b/lldb/source/Plugins/Platform/AIX/PlatformAIX.h
index 92b4f6c0ed426..b7f6a62f65c9f 100644
--- a/lldb/source/Plugins/Platform/AIX/PlatformAIX.h
+++ b/lldb/source/Plugins/Platform/AIX/PlatformAIX.h
@@ -47,7 +47,7 @@ class PlatformAIX : public PlatformPOSIX {
 
   void CalculateTrapHandlerSymbolNames() override;
 
-  lldb::UnwindPlanSP GetTrapHandlerUnwindPlan(const llvm::Triple &triple,
+  lldb::UnwindPlanSP GetTrapHandlerUnwindPlan(const ArchSpec &arch,
                                               ConstString name) override;
 
   MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr,

diff  --git a/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
index da14da44f5939..932234521ccf5 100644
--- a/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
+++ b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
@@ -15,6 +15,7 @@
 #endif
 
 #include "Plugins/Process/Utility/LinuxSignals.h"
+#include "Plugins/Process/Utility/lldb-riscv-register-enums.h"
 #include "Utility/ARM64_DWARF_Registers.h"
 #include "lldb/Core/Debugger.h"
 #include "lldb/Core/PluginManager.h"
@@ -22,6 +23,7 @@
 #include "lldb/Symbol/UnwindPlan.h"
 #include "lldb/Target/Process.h"
 #include "lldb/Target/Target.h"
+#include "lldb/Utility/ArchSpec.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Log.h"
@@ -220,6 +222,7 @@ void PlatformLinux::CalculateTrapHandlerSymbolNames() {
   m_trap_handlers.push_back(ConstString("_sigtramp"));
   m_trap_handlers.push_back(ConstString("__kernel_rt_sigreturn"));
   m_trap_handlers.push_back(ConstString("__restore_rt"));
+  m_trap_handlers.push_back(ConstString("__vdso_rt_sigreturn"));
 }
 
 static lldb::UnwindPlanSP GetAArch64TrapHandlerUnwindPlan(ConstString name) {
@@ -302,12 +305,92 @@ static lldb::UnwindPlanSP GetAArch64TrapHandlerUnwindPlan(ConstString name) {
   return unwind_plan_sp;
 }
 
-lldb::UnwindPlanSP
-PlatformLinux::GetTrapHandlerUnwindPlan(const llvm::Triple &triple,
-                                        ConstString name) {
+static lldb::UnwindPlanSP GetRISCVTrapHandlerUnwindPlan(ConstString name,
+                                                        uint32_t fp_flags) {
+  if (name != "__vdso_rt_sigreturn")
+    return {};
+
+  UnwindPlan::Row row;
+
+  // In the signal trampoline frame, sp points to an rt_sigframe[1], which is:
+  //  - 128-byte siginfo struct
+  //  - ucontext struct:
+  //     - 8-byte long (uc_flags)
+  //     - 8-byte pointer (*uc_link)
+  //     - 24-byte struct (uc_stack)
+  //     - 8-byte struct (uc_sigmask)
+  //     - 120-byte of padding to allow sigset_t to be expanded in the future
+  //     - 8 bytes of padding because sigcontext has 16-byte alignment
+  //     - struct sigcontext uc_mcontext
+  // [1]
+  // https://github.com/torvalds/linux/blob/master/arch/riscv/kernel/signal.c
+
+  constexpr size_t siginfo_size = 128;
+  constexpr size_t uc_flags_size = 8;
+  constexpr size_t uc_link_ptr_size = 8;
+  constexpr size_t uc_stack_size = 24;
+  constexpr size_t uc_sigmask_size = 8;
+  constexpr size_t padding_size = 128;
+
+  constexpr size_t offset = siginfo_size + uc_flags_size + uc_link_ptr_size +
+                            uc_stack_size + uc_sigmask_size + padding_size;
+
+  // In user_regs_struct GPRs are always 64-bit length
+  size_t gpr_size = 8;
+  row.GetCFAValue().SetIsRegisterPlusOffset(gpr_sp_riscv, offset);
+  for (uint32_t reg_num = gpr_first_riscv; reg_num < gpr_first_riscv + 32;
+       ++reg_num)
+    row.SetRegisterLocationToAtCFAPlusOffset(reg_num, reg_num * gpr_size,
+                                             false);
+
+  size_t fpr_size = 0;
+  switch (fp_flags) {
+  case ArchSpec::eRISCV_float_abi_soft:
+    fpr_size = 0;
+    break;
+  case ArchSpec::eRISCV_float_abi_single:
+    fpr_size = 4;
+    break;
+  case ArchSpec::eRISCV_float_abi_double:
+    fpr_size = 8;
+    break;
+  case ArchSpec::eRISCV_float_abi_quad:
+    fpr_size = 16;
+    break;
+  }
+
+  if (fpr_size != 0) {
+    for (uint32_t reg_num = fpr_first_riscv; reg_num < fpr_first_riscv + 32;
+         ++reg_num) {
+      size_t fpr_offset =
+          gpr_size * 32 + (reg_num - fpr_first_riscv) * fpr_size;
+      row.SetRegisterLocationToAtCFAPlusOffset(reg_num, fpr_offset, false);
+    }
+
+    size_t fpr_fcsr_offset = gpr_size * 32 + fpr_size * 32;
+    row.SetRegisterLocationToAtCFAPlusOffset(fpr_fcsr_riscv, fpr_fcsr_offset,
+                                             false);
+  }
+
+  UnwindPlanSP unwind_plan_sp = std::make_shared<UnwindPlan>(eRegisterKindLLDB);
+  unwind_plan_sp->AppendRow(std::move(row));
+  unwind_plan_sp->SetSourceName("RISC-V Linux sigcontext");
+  unwind_plan_sp->SetSourcedFromCompiler(eLazyBoolYes);
+  unwind_plan_sp->SetUnwindPlanValidAtAllInstructions(eLazyBoolNo);
+  unwind_plan_sp->SetUnwindPlanForSignalTrap(eLazyBoolYes);
+
+  return unwind_plan_sp;
+}
+
+lldb::UnwindPlanSP PlatformLinux::GetTrapHandlerUnwindPlan(const ArchSpec &arch,
+                                                           ConstString name) {
+  llvm::Triple triple = arch.GetTriple();
   if (triple.isAArch64())
     return GetAArch64TrapHandlerUnwindPlan(name);
-
+  if (triple.isRISCV()) {
+    uint32_t fp_flags = arch.GetFlags() & ArchSpec::eRISCV_float_abi_mask;
+    return GetRISCVTrapHandlerUnwindPlan(name, fp_flags);
+  }
   return {};
 }
 

diff  --git a/lldb/source/Plugins/Platform/Linux/PlatformLinux.h b/lldb/source/Plugins/Platform/Linux/PlatformLinux.h
index 0fd33b03dcd23..cf6a60874b04e 100644
--- a/lldb/source/Plugins/Platform/Linux/PlatformLinux.h
+++ b/lldb/source/Plugins/Platform/Linux/PlatformLinux.h
@@ -52,7 +52,7 @@ class PlatformLinux : public PlatformPOSIX {
 
   void CalculateTrapHandlerSymbolNames() override;
 
-  lldb::UnwindPlanSP GetTrapHandlerUnwindPlan(const llvm::Triple &triple,
+  lldb::UnwindPlanSP GetTrapHandlerUnwindPlan(const ArchSpec &arch,
                                               ConstString name) override;
 
   MmapArgList GetMmapArgumentList(const ArchSpec &arch, lldb::addr_t addr,

diff  --git a/lldb/source/Target/RegisterContextUnwind.cpp b/lldb/source/Target/RegisterContextUnwind.cpp
index 252bee2b5d72a..0755d21bc8cc4 100644
--- a/lldb/source/Target/RegisterContextUnwind.cpp
+++ b/lldb/source/Target/RegisterContextUnwind.cpp
@@ -907,9 +907,9 @@ RegisterContextUnwind::GetFullUnwindPlanForFrame() {
     // substitute plan. Otherwise, use eh_frame.
     if (m_sym_ctx_valid) {
       lldb::PlatformSP platform = process->GetTarget().GetPlatform();
+      const ArchSpec arch = process->GetTarget().GetArchitecture();
       if (auto unwind_plan_sp = platform->GetTrapHandlerUnwindPlan(
-              process->GetTarget().GetArchitecture().GetTriple(),
-              GetSymbolOrFunctionName(m_sym_ctx)))
+              arch, GetSymbolOrFunctionName(m_sym_ctx)))
         return unwind_plan_sp;
     }
 


        


More information about the llvm-branch-commits mailing list