Skip to content

Commit

Permalink
[lldb] Don't scan more than 10MB of assembly insns (llvm#105890)
Browse files Browse the repository at this point in the history
For supported architectures, lldb will do a static scan of the assembly
instructions of a function to detect stack/frame pointer changes,
register stores and loads, so we can retrieve register values for the
caller stack frames. We trust that the function address range reflects
the actual function range, but in a stripped binary or other unusual
environment, we can end up scanning all of the text as a single
"function" which is (1) incorrect and useless, but more importantly (2)
slow.

Cap the max size we will profile to 10MB of instructions. There will
surely be functions longer than this with no unwind info, and we will
miss the final epilogue or mid-function epilogues past the first 10MB,
but I think this will be unusual, and the failure more to missing the
epilogue is that the user will need to step out an extra time or two as
the StackID is not correctly calculated mid-epilogue. I think this is a
good tradeoff of behaviors.

rdar://134391577
  • Loading branch information
jasonmolenda authored Aug 27, 2024
1 parent 67eb727 commit 3280292
Showing 1 changed file with 11 additions and 1 deletion.
12 changes: 11 additions & 1 deletion lldb/source/Symbol/FuncUnwinders.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -334,12 +334,22 @@ UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target,

m_tried_unwind_plan_assembly = true;

// Don't analyze more than 10 megabytes of instructions,
// if a function is legitimately larger than that, we'll
// miss the epilogue instructions, but guard against a
// bogusly large function and analyzing large amounts of
// non-instruction data.
AddressRange range = m_range;
const addr_t func_size =
std::min(range.GetByteSize(), (addr_t)1024 * 10 * 10);
range.SetByteSize(func_size);

UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
if (assembly_profiler_sp) {
m_unwind_plan_assembly_sp =
std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
m_range, thread, *m_unwind_plan_assembly_sp)) {
range, thread, *m_unwind_plan_assembly_sp)) {
m_unwind_plan_assembly_sp.reset();
}
}
Expand Down

0 comments on commit 3280292

Please sign in to comment.