Skip to content

[lldb] Return *const* UnwindPlan pointers from FuncUnwinders #133247

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 2, 2025
Merged
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
78 changes: 41 additions & 37 deletions lldb/include/lldb/Symbol/FuncUnwinders.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,19 @@ class FuncUnwinders {

~FuncUnwinders();

lldb::UnwindPlanSP GetUnwindPlanAtCallSite(Target &target, Thread &thread);
std::shared_ptr<const UnwindPlan> GetUnwindPlanAtCallSite(Target &target,
Copy link
Member

Choose a reason for hiding this comment

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

Can we change the UnwindPlanSP typedef? Do we ever need a non-const UnwindPlan shared pointer?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Currently we need them, because the unwind plans are (sometimes) stored in a shared pointer while they are being constructed. That could be avoided because we don't really need the shared ownership at that point (they could be a unique_ptr or a value). However, I'm not particularly thrilled with the idea of repurposing UnwindPlanSP for this, as I think that would be surprising -- there's nothing in that name that indicates this is a const pointer, and I think it's important to see that.

One idea I have had that could solve this (but have never found the time to propose) is to replace the individual FoobarSP typedefs with a SP = std::shared_ptr<T> template alias. That would let us write SP<const Foobar> in exactly the places which need it; and it might also help with the hypothetical migration to the llvm naming convention (frees up FoobarSP as a member name)

Copy link
Member

Choose a reason for hiding this comment

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

Makes sense.

One idea I have had that could solve this (but have never found the time to propose) is to replace the individual FoobarSP typedefs with a SP = std::shared_ptr template alias. That would let us write SP in exactly the places which need it; and it might also help with the hypothetical migration to the llvm naming convention (frees up FoobarSP as a member name)

Yeah, I remember you suggesting that in https://reviews.llvm.org/D133906. At the time I played around with a regex/python script to replace the existing FoobarSPs and it somehow was a lot harder to get right than I expected.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Heh, that seems like quite a long time ago. Well.. I guess I'm at least consistent :)

I didn't realize you were actually experimenting with that approach. I'm going to take this to mean that such an idea has a non-zero chance of being accepted :) (ofc, there should be an rfc for that, and ideally some semi-automated method/tool to do the conversion)

Thread &thread);

lldb::UnwindPlanSP GetUnwindPlanAtNonCallSite(Target &target,
lldb_private::Thread &thread);
std::shared_ptr<const UnwindPlan>
GetUnwindPlanAtNonCallSite(Target &target, lldb_private::Thread &thread);

lldb::UnwindPlanSP GetUnwindPlanFastUnwind(Target &target,
lldb_private::Thread &thread);
std::shared_ptr<const UnwindPlan>
GetUnwindPlanFastUnwind(Target &target, lldb_private::Thread &thread);

lldb::UnwindPlanSP
std::shared_ptr<const UnwindPlan>
GetUnwindPlanArchitectureDefault(lldb_private::Thread &thread);

lldb::UnwindPlanSP
std::shared_ptr<const UnwindPlan>
GetUnwindPlanArchitectureDefaultAtFunctionEntry(lldb_private::Thread &thread);

Address &GetFirstNonPrologueInsn(Target &target);
Expand Down Expand Up @@ -77,32 +78,34 @@ class FuncUnwinders {
// used. Instead, clients should ask for the *behavior* they are looking for,
// using one of the above UnwindPlan retrieval methods.

lldb::UnwindPlanSP GetAssemblyUnwindPlan(Target &target, Thread &thread);
std::shared_ptr<const UnwindPlan> GetAssemblyUnwindPlan(Target &target,
Thread &thread);

lldb::UnwindPlanSP GetObjectFileUnwindPlan(Target &target);
std::shared_ptr<const UnwindPlan> GetObjectFileUnwindPlan(Target &target);

lldb::UnwindPlanSP GetObjectFileAugmentedUnwindPlan(Target &target,
Thread &thread);
std::shared_ptr<const UnwindPlan>
GetObjectFileAugmentedUnwindPlan(Target &target, Thread &thread);

lldb::UnwindPlanSP GetEHFrameUnwindPlan(Target &target);
std::shared_ptr<const UnwindPlan> GetEHFrameUnwindPlan(Target &target);

lldb::UnwindPlanSP GetEHFrameAugmentedUnwindPlan(Target &target,
Thread &thread);
std::shared_ptr<const UnwindPlan>
GetEHFrameAugmentedUnwindPlan(Target &target, Thread &thread);

lldb::UnwindPlanSP GetDebugFrameUnwindPlan(Target &target);
std::shared_ptr<const UnwindPlan> GetDebugFrameUnwindPlan(Target &target);

lldb::UnwindPlanSP GetDebugFrameAugmentedUnwindPlan(Target &target,
Thread &thread);
std::shared_ptr<const UnwindPlan>
GetDebugFrameAugmentedUnwindPlan(Target &target, Thread &thread);

lldb::UnwindPlanSP GetCompactUnwindUnwindPlan(Target &target);
std::shared_ptr<const UnwindPlan> GetCompactUnwindUnwindPlan(Target &target);

lldb::UnwindPlanSP GetArmUnwindUnwindPlan(Target &target);
std::shared_ptr<const UnwindPlan> GetArmUnwindUnwindPlan(Target &target);

lldb::UnwindPlanSP GetSymbolFileUnwindPlan(Thread &thread);
std::shared_ptr<const UnwindPlan> GetSymbolFileUnwindPlan(Thread &thread);

lldb::UnwindPlanSP GetArchDefaultUnwindPlan(Thread &thread);
std::shared_ptr<const UnwindPlan> GetArchDefaultUnwindPlan(Thread &thread);

lldb::UnwindPlanSP GetArchDefaultAtFuncEntryUnwindPlan(Thread &thread);
std::shared_ptr<const UnwindPlan>
GetArchDefaultAtFuncEntryUnwindPlan(Thread &thread);

private:
lldb::UnwindAssemblySP GetUnwindAssemblyProfiler(Target &target);
Expand All @@ -113,7 +116,8 @@ class FuncUnwinders {
// unwind rule for the pc, and LazyBoolCalculate if it was unable to
// determine this for some reason.
lldb_private::LazyBool CompareUnwindPlansForIdenticalInitialPCLocation(
Thread &thread, const lldb::UnwindPlanSP &a, const lldb::UnwindPlanSP &b);
Thread &thread, const std::shared_ptr<const UnwindPlan> &a,
const std::shared_ptr<const UnwindPlan> &b);

UnwindTable &m_unwind_table;

Expand All @@ -129,22 +133,22 @@ class FuncUnwinders {

std::recursive_mutex m_mutex;

lldb::UnwindPlanSP m_unwind_plan_assembly_sp;
lldb::UnwindPlanSP m_unwind_plan_object_file_sp;
lldb::UnwindPlanSP m_unwind_plan_eh_frame_sp;
lldb::UnwindPlanSP m_unwind_plan_debug_frame_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_assembly_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_object_file_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_eh_frame_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_debug_frame_sp;

// augmented by assembly inspection so it's valid everywhere
lldb::UnwindPlanSP m_unwind_plan_object_file_augmented_sp;
lldb::UnwindPlanSP m_unwind_plan_eh_frame_augmented_sp;
lldb::UnwindPlanSP m_unwind_plan_debug_frame_augmented_sp;

std::vector<lldb::UnwindPlanSP> m_unwind_plan_compact_unwind;
lldb::UnwindPlanSP m_unwind_plan_arm_unwind_sp;
lldb::UnwindPlanSP m_unwind_plan_symbol_file_sp;
lldb::UnwindPlanSP m_unwind_plan_fast_sp;
lldb::UnwindPlanSP m_unwind_plan_arch_default_sp;
lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_object_file_augmented_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_eh_frame_augmented_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_debug_frame_augmented_sp;

std::vector<std::shared_ptr<const UnwindPlan>> m_unwind_plan_compact_unwind;
std::shared_ptr<const UnwindPlan> m_unwind_plan_arm_unwind_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_symbol_file_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_fast_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_arch_default_sp;
std::shared_ptr<const UnwindPlan> m_unwind_plan_arch_default_at_func_entry_sp;

// Fetching the UnwindPlans can be expensive - if we've already attempted to
// get one & failed, don't try again.
Expand Down
4 changes: 2 additions & 2 deletions lldb/include/lldb/Symbol/UnwindPlan.h
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ class UnwindPlan {
m_return_addr_register = regnum;
}

uint32_t GetReturnAddressRegister() { return m_return_addr_register; }
uint32_t GetReturnAddressRegister() const { return m_return_addr_register; }

uint32_t GetInitialCFARegister() const {
if (m_row_list.empty())
Expand All @@ -479,7 +479,7 @@ class UnwindPlan {
m_plan_valid_ranges = std::move(ranges);
}

bool PlanValidAtAddress(Address addr);
bool PlanValidAtAddress(Address addr) const;

bool IsValidRowIndex(uint32_t idx) const;

Expand Down
16 changes: 9 additions & 7 deletions lldb/include/lldb/Target/RegisterContextUnwind.h
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,8 @@ class RegisterContextUnwind : public lldb_private::RegisterContext {

/// Check if the given unwind plan indicates a signal trap handler, and
/// update frame type and symbol context if so.
void PropagateTrapHandlerFlagFromUnwindPlan(lldb::UnwindPlanSP unwind_plan);
void PropagateTrapHandlerFlagFromUnwindPlan(
std::shared_ptr<const UnwindPlan> unwind_plan);

// Provide a location for where THIS function saved the CALLER's register
// value
Expand Down Expand Up @@ -194,16 +195,17 @@ class RegisterContextUnwind : public lldb_private::RegisterContext {
const UnwindPlan::Row::FAValue &fa,
lldb::addr_t &address);

lldb::UnwindPlanSP GetFastUnwindPlanForFrame();
std::shared_ptr<const UnwindPlan> GetFastUnwindPlanForFrame();

lldb::UnwindPlanSP GetFullUnwindPlanForFrame();
std::shared_ptr<const UnwindPlan> GetFullUnwindPlanForFrame();

void UnwindLogMsg(const char *fmt, ...) __attribute__((format(printf, 2, 3)));

void UnwindLogMsgVerbose(const char *fmt, ...)
__attribute__((format(printf, 2, 3)));

bool IsUnwindPlanValidForCurrentPC(lldb::UnwindPlanSP unwind_plan_sp);
bool IsUnwindPlanValidForCurrentPC(
std::shared_ptr<const UnwindPlan> unwind_plan_sp);

lldb::addr_t GetReturnAddressHint(int32_t plan_offset);

Expand All @@ -215,9 +217,9 @@ class RegisterContextUnwind : public lldb_private::RegisterContext {
// i.e. where THIS frame saved them
///

lldb::UnwindPlanSP m_fast_unwind_plan_sp; // may be NULL
lldb::UnwindPlanSP m_full_unwind_plan_sp;
lldb::UnwindPlanSP m_fallback_unwind_plan_sp; // may be NULL
std::shared_ptr<const UnwindPlan> m_fast_unwind_plan_sp; // may be NULL
std::shared_ptr<const UnwindPlan> m_full_unwind_plan_sp;
std::shared_ptr<const UnwindPlan> m_fallback_unwind_plan_sp; // may be NULL

bool m_all_registers_available; // Can we retrieve all regs or just
// nonvolatile regs?
Expand Down
106 changes: 49 additions & 57 deletions lldb/source/Commands/CommandObjectTarget.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3641,85 +3641,78 @@ class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {

result.GetOutputStream().Printf("\n");

UnwindPlanSP non_callsite_unwind_plan =
func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread);
if (non_callsite_unwind_plan) {
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetUnwindPlanAtNonCallSite(*target, *thread)) {
result.GetOutputStream().Printf(
"Asynchronous (not restricted to call-sites) UnwindPlan is '%s'\n",
non_callsite_unwind_plan->GetSourceName().AsCString());
plan_sp->GetSourceName().AsCString());
}
UnwindPlanSP callsite_unwind_plan =
func_unwinders_sp->GetUnwindPlanAtCallSite(*target, *thread);
if (callsite_unwind_plan) {
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetUnwindPlanAtCallSite(*target, *thread)) {
result.GetOutputStream().Printf(
"Synchronous (restricted to call-sites) UnwindPlan is '%s'\n",
callsite_unwind_plan->GetSourceName().AsCString());
plan_sp->GetSourceName().AsCString());
}
UnwindPlanSP fast_unwind_plan =
func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread);
if (fast_unwind_plan) {
result.GetOutputStream().Printf(
"Fast UnwindPlan is '%s'\n",
fast_unwind_plan->GetSourceName().AsCString());
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread)) {
result.GetOutputStream().Printf("Fast UnwindPlan is '%s'\n",
plan_sp->GetSourceName().AsCString());
}

result.GetOutputStream().Printf("\n");

UnwindPlanSP assembly_sp =
func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread);
if (assembly_sp) {
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetAssemblyUnwindPlan(*target, *thread)) {
result.GetOutputStream().Printf(
"Assembly language inspection UnwindPlan:\n");
assembly_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
result.GetOutputStream().Printf("\n");
}

UnwindPlanSP of_unwind_sp =
func_unwinders_sp->GetObjectFileUnwindPlan(*target);
if (of_unwind_sp) {
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetObjectFileUnwindPlan(*target)) {
result.GetOutputStream().Printf("object file UnwindPlan:\n");
of_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
result.GetOutputStream().Printf("\n");
}

UnwindPlanSP of_unwind_augmented_sp =
func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target, *thread);
if (of_unwind_augmented_sp) {
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target,
*thread)) {
result.GetOutputStream().Printf("object file augmented UnwindPlan:\n");
of_unwind_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
result.GetOutputStream().Printf("\n");
}

UnwindPlanSP ehframe_sp =
func_unwinders_sp->GetEHFrameUnwindPlan(*target);
if (ehframe_sp) {
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetEHFrameUnwindPlan(*target)) {
result.GetOutputStream().Printf("eh_frame UnwindPlan:\n");
ehframe_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
result.GetOutputStream().Printf("\n");
}

UnwindPlanSP ehframe_augmented_sp =
func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target, *thread);
if (ehframe_augmented_sp) {
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetEHFrameAugmentedUnwindPlan(*target,
*thread)) {
result.GetOutputStream().Printf("eh_frame augmented UnwindPlan:\n");
ehframe_augmented_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
result.GetOutputStream().Printf("\n");
}

if (UnwindPlanSP plan_sp =
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetDebugFrameUnwindPlan(*target)) {
result.GetOutputStream().Printf("debug_frame UnwindPlan:\n");
plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
result.GetOutputStream().Printf("\n");
}

if (UnwindPlanSP plan_sp =
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetDebugFrameAugmentedUnwindPlan(*target,
*thread)) {
result.GetOutputStream().Printf("debug_frame augmented UnwindPlan:\n");
Expand All @@ -3728,36 +3721,35 @@ class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed {
result.GetOutputStream().Printf("\n");
}

UnwindPlanSP arm_unwind_sp =
func_unwinders_sp->GetArmUnwindUnwindPlan(*target);
if (arm_unwind_sp) {
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetArmUnwindUnwindPlan(*target)) {
result.GetOutputStream().Printf("ARM.exidx unwind UnwindPlan:\n");
arm_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
result.GetOutputStream().Printf("\n");
}

if (UnwindPlanSP symfile_plan_sp =
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetSymbolFileUnwindPlan(*thread)) {
result.GetOutputStream().Printf("Symbol file UnwindPlan:\n");
symfile_plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
result.GetOutputStream().Printf("\n");
}

UnwindPlanSP compact_unwind_sp =
func_unwinders_sp->GetCompactUnwindUnwindPlan(*target);
if (compact_unwind_sp) {
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetCompactUnwindUnwindPlan(*target)) {
result.GetOutputStream().Printf("Compact unwind UnwindPlan:\n");
compact_unwind_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
result.GetOutputStream().Printf("\n");
}

if (fast_unwind_plan) {
if (std::shared_ptr<const UnwindPlan> plan_sp =
func_unwinders_sp->GetUnwindPlanFastUnwind(*target, *thread)) {
result.GetOutputStream().Printf("Fast UnwindPlan:\n");
fast_unwind_plan->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
plan_sp->Dump(result.GetOutputStream(), thread.get(),
LLDB_INVALID_ADDRESS);
result.GetOutputStream().Printf("\n");
}

Expand Down
Loading
Loading