Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions lldb/include/lldb/Target/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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 {};
}

Expand Down
4 changes: 4 additions & 0 deletions lldb/source/Plugins/ABI/RISCV/ABISysV_riscv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand All @@ -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;
}

Expand Down
5 changes: 2 additions & 3 deletions lldb/source/Plugins/Platform/AIX/PlatformAIX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 {};
}

Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Platform/AIX/PlatformAIX.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
87 changes: 83 additions & 4 deletions lldb/source/Plugins/Platform/Linux/PlatformLinux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,15 @@
#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"
#include "lldb/Host/HostInfo.h"
#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"
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -302,12 +305,88 @@ 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;

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);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need a row to say where pc is stored? It's not part of regs 0-31, as far as I can tell.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, pc register is a part of regs 0-31:

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, interesting.

Should we be pointing to the FP regs in uc_mcontext too?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your comment, I added FP regs recovery in this plan


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) {
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 {};
}

Expand Down
2 changes: 1 addition & 1 deletion lldb/source/Plugins/Platform/Linux/PlatformLinux.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions lldb/source/Target/RegisterContextUnwind.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
Loading