[Lldb-commits] [lldb] [lldb] Don't scan more than 10MB of assembly insns (PR #105890)
Jason Molenda via lldb-commits
lldb-commits at lists.llvm.org
Fri Aug 23 14:14:29 PDT 2024
https://github.com/jasonmolenda created https://github.com/llvm/llvm-project/pull/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
>From fe4da52529c3a5988ecabe6289951c5e6833c6f7 Mon Sep 17 00:00:00 2001
From: Jason Molenda <jmolenda at apple.com>
Date: Fri, 23 Aug 2024 14:09:21 -0700
Subject: [PATCH] [lldb] Don't scan more than 10MB of assembly insns
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
---
lldb/source/Symbol/FuncUnwinders.cpp | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/lldb/source/Symbol/FuncUnwinders.cpp b/lldb/source/Symbol/FuncUnwinders.cpp
index d67c0a828eb350..228d9a1072deca 100644
--- a/lldb/source/Symbol/FuncUnwinders.cpp
+++ b/lldb/source/Symbol/FuncUnwinders.cpp
@@ -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();
}
}
More information about the lldb-commits
mailing list