[Lldb-commits] [lldb] [lldb][RISCV] Implement trap handler unwind plan (PR #166531)
Georgiy Samoylov via lldb-commits
lldb-commits at lists.llvm.org
Mon Nov 17 06:10:31 PST 2025
https://github.com/sga-sc updated https://github.com/llvm/llvm-project/pull/166531
>From 5338f92545bfba30af2e1240af5e4a01286293db Mon Sep 17 00:00:00 2001
From: Georgiy Samoylov <g.samoylov at syntacore.com>
Date: Thu, 23 Oct 2025 13:12:32 +0300
Subject: [PATCH 1/3] [lldb][RISCV] Implement trap handler unwind plan
---
lldb/include/lldb/Target/Platform.h | 8 +-
.../Plugins/Platform/Linux/PlatformLinux.cpp | 89 ++++++++++++++++++-
.../Plugins/Platform/Linux/PlatformLinux.h | 2 +-
lldb/source/Target/RegisterContextUnwind.cpp | 4 +-
4 files changed, 92 insertions(+), 11 deletions(-)
diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h
index 35ffdabf907e7..7bedde92b81a2 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/Platform/Linux/PlatformLinux.cpp b/lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
index da14da44f5939..01afcdce3644a 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,90 @@ 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 UnwindPlanSP{};
+
+ 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;
+
+ 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 * 8, 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;
+ default:
+ llvm_unreachable("Invalid RISC-V FP flags");
+ }
+
+ if (fpr_size != 0) {
+ for (uint32_t reg_num = fpr_first_riscv; reg_num < fpr_first_riscv + 32;
+ ++reg_num) {
+ row.SetRegisterLocationToAtCFAPlusOffset(reg_num, reg_num * fpr_size,
+ false);
+ }
+
+ // CSR for FP registers always has 32-bit length
+ row.SetRegisterLocationToAtCFAPlusOffset(fpr_fcsr_riscv, fpr_fcsr_riscv * 4,
+ 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(eLazyBoolNo);
+ 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;
}
>From 24120c8e72375733eab769b0c50ad10cde236417 Mon Sep 17 00:00:00 2001
From: Georgiy Samoylov <g.samoylov at syntacore.com>
Date: Thu, 23 Oct 2025 13:34:54 +0300
Subject: [PATCH 2/3] [lldb][RISCV] Mark default unwind plans they couldn't be
used for trap handling
After we introduced a special unwind plan for trap handling, we should
mark that other unwind plans for RISC-V can't be used in the same case.
---
lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp | 4 ++++
1 file changed, 4 insertions(+)
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;
}
>From ce0795284cf411cf51c29065ca6925b9a6e92992 Mon Sep 17 00:00:00 2001
From: Georgiy Samoylov <g.samoylov at syntacore.com>
Date: Mon, 17 Nov 2025 16:47:34 +0300
Subject: [PATCH 3/3] [lldb] Change GetTrapHandlerUnwindPlan interface
---
lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp | 5 ++---
lldb/source/Plugins/Platform/AIX/PlatformAIX.h | 2 +-
2 files changed, 3 insertions(+), 4 deletions(-)
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,
More information about the lldb-commits
mailing list