Add a way for an ObjectFile to indicate that assembly emulation
should not be used for this module -- for use when an ObjectFile
knows that it does not have meaningful or accurate function start
addresses.
More commonly, it is not clear that function start addresses are
missing in a module. There are certain cases on Mac OS X where we
can tell that a Mach-O binary has been stripped of this essential
information, and the unwinder can end up emulating many megabytes
of instructions for a single "function" in the binary.
When a Mach-O binary is missing both an LC_FUNCTION_STARTS load
command (very unusual) and an eh_frame section, then we will assume
it has also been stripped of symbols and that instruction emulation
will not be useful on this module.
<rdar://problem/25988067>
llvm-svn: 268475
diff --git a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
index 9bd930f..09fc922 100644
--- a/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
+++ b/lldb/source/Plugins/ObjectFile/Mach-O/ObjectFileMachO.cpp
@@ -1130,7 +1130,9 @@
m_mach_sections(),
m_entry_point_address(),
m_thread_context_offsets(),
- m_thread_context_offsets_valid(false)
+ m_thread_context_offsets_valid(false),
+ m_reexported_dylibs (),
+ m_allow_assembly_emulation_unwind_plans (true)
{
::memset (&m_header, 0, sizeof(m_header));
::memset (&m_dysymtab, 0, sizeof(m_dysymtab));
@@ -1145,7 +1147,9 @@
m_mach_sections(),
m_entry_point_address(),
m_thread_context_offsets(),
- m_thread_context_offsets_valid(false)
+ m_thread_context_offsets_valid(false),
+ m_reexported_dylibs (),
+ m_allow_assembly_emulation_unwind_plans (true)
{
::memset (&m_header, 0, sizeof(m_header));
::memset (&m_dysymtab, 0, sizeof(m_dysymtab));
@@ -2603,6 +2607,18 @@
const size_t function_starts_count = function_starts.GetSize();
+ if (function_starts_count == 0)
+ {
+ // No LC_FUNCTION_STARTS/eh_frame section in this binary, we're going to assume the binary
+ // has been stripped. Don't allow assembly language instruction emulation because we don't
+ // know proper function start boundaries.
+ m_allow_assembly_emulation_unwind_plans = false;
+ Log *unwind_or_symbol_log (lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_UNWIND));
+
+ if (unwind_or_symbol_log)
+ module_sp->LogMessage(unwind_or_symbol_log, "no LC_FUNCTION_STARTS, will not allow assembly profiled unwinds");
+ }
+
const user_id_t TEXT_eh_frame_sectID =
eh_frame_section_sp.get() ? eh_frame_section_sp->GetID()
: static_cast<user_id_t>(NO_SECT);
@@ -5624,6 +5640,12 @@
return m_header.filetype == llvm::MachO::MH_DYLINKER;
}
+bool
+ObjectFileMachO::AllowAssemblyEmulationUnwindPlans ()
+{
+ return m_allow_assembly_emulation_unwind_plans;
+}
+
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------