Skip to content

Commit 3280292

Browse files
authored
[lldb] Don't scan more than 10MB of assembly insns (#105890)
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
1 parent 67eb727 commit 3280292

File tree

1 file changed

+11
-1
lines changed

1 file changed

+11
-1
lines changed

lldb/source/Symbol/FuncUnwinders.cpp

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,12 +334,22 @@ UnwindPlanSP FuncUnwinders::GetAssemblyUnwindPlan(Target &target,
334334

335335
m_tried_unwind_plan_assembly = true;
336336

337+
// Don't analyze more than 10 megabytes of instructions,
338+
// if a function is legitimately larger than that, we'll
339+
// miss the epilogue instructions, but guard against a
340+
// bogusly large function and analyzing large amounts of
341+
// non-instruction data.
342+
AddressRange range = m_range;
343+
const addr_t func_size =
344+
std::min(range.GetByteSize(), (addr_t)1024 * 10 * 10);
345+
range.SetByteSize(func_size);
346+
337347
UnwindAssemblySP assembly_profiler_sp(GetUnwindAssemblyProfiler(target));
338348
if (assembly_profiler_sp) {
339349
m_unwind_plan_assembly_sp =
340350
std::make_shared<UnwindPlan>(lldb::eRegisterKindGeneric);
341351
if (!assembly_profiler_sp->GetNonCallSiteUnwindPlanFromAssembly(
342-
m_range, thread, *m_unwind_plan_assembly_sp)) {
352+
range, thread, *m_unwind_plan_assembly_sp)) {
343353
m_unwind_plan_assembly_sp.reset();
344354
}
345355
}

0 commit comments

Comments
 (0)