summaryrefslogtreecommitdiffstats
path: root/lldb/source/Symbol/UnwindTable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lldb/source/Symbol/UnwindTable.cpp')
-rw-r--r--lldb/source/Symbol/UnwindTable.cpp132
1 files changed, 132 insertions, 0 deletions
diff --git a/lldb/source/Symbol/UnwindTable.cpp b/lldb/source/Symbol/UnwindTable.cpp
new file mode 100644
index 00000000000..dcab1933375
--- /dev/null
+++ b/lldb/source/Symbol/UnwindTable.cpp
@@ -0,0 +1,132 @@
+//===-- UnwindTable.cpp ----------------------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Symbol/ObjectFile.h"
+
+#include "lldb/Symbol/FuncUnwinders.h"
+#include "lldb/Symbol/SymbolContext.h"
+#include "lldb/Core/Section.h"
+#include "lldb/Core/Module.h"
+#include "lldb/lldb-forward.h"
+#include "lldb/Utility/UnwindAssemblyProfiler.h"
+#include "lldb/Symbol/DWARFCallFrameInfo.h"
+
+#include "lldb/Symbol/UnwindTable.h"
+#include <stdio.h>
+
+// There is one UnwindTable object per ObjectFile.
+// It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile.
+// Each Unwind object has multiple UnwindPlans for different scenarios.
+
+using namespace lldb;
+using namespace lldb_private;
+
+UnwindTable::UnwindTable (ObjectFile& objfile) : m_object_file(objfile),
+ m_unwinds(),
+ m_initialized(false),
+ m_eh_frame(NULL),
+ m_assembly_profiler(NULL)
+{
+}
+
+// We can't do some of this initialization when the ObjectFile is running its ctor; delay doing it
+// until needed for something.
+
+void
+UnwindTable::initialize ()
+{
+ if (m_initialized)
+ return;
+
+ SectionList* sl = m_object_file.GetSectionList ();
+ if (sl)
+ {
+ SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true);
+ if (sect.get())
+ {
+ m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true);
+ }
+ }
+
+ ArchSpec arch;
+ ConstString str;
+ m_object_file.GetTargetTriple (str);
+ arch.SetArchFromTargetTriple (str.GetCString());
+ m_assembly_profiler = UnwindAssemblyProfiler::FindPlugin (arch);
+
+ m_initialized = true;
+}
+
+UnwindTable::~UnwindTable ()
+{
+ if (m_eh_frame)
+ delete m_eh_frame;
+}
+
+FuncUnwindersSP
+UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
+{
+ FuncUnwindersSP no_unwind_found;
+
+ initialize();
+
+ // Create a FuncUnwinders object for the binary search below
+ AddressRange search_range(addr, 1);
+ FuncUnwindersSP search_unwind(new FuncUnwinders (*this, NULL, search_range));
+
+ const_iterator idx;
+ idx = std::lower_bound (m_unwinds.begin(), m_unwinds.end(), search_unwind);
+
+ bool found_match = true;
+ if (m_unwinds.size() == 0)
+ {
+ found_match = false;
+ }
+ else if (idx == m_unwinds.end())
+ {
+ --idx;
+ }
+ if (idx != m_unwinds.begin() && (*idx)->GetFunctionStartAddress().GetOffset() != addr.GetOffset())
+ {
+ --idx;
+ }
+ if (found_match && (*idx)->ContainsAddress (addr))
+ {
+ return *idx;
+ }
+
+ AddressRange range;
+ if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range))
+ {
+ FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range));
+ m_unwinds.push_back (unw);
+ std::sort (m_unwinds.begin(), m_unwinds.end());
+ return unw;
+ }
+ else
+ {
+ // Does the eh_frame unwind info has a function bounds defined for this addr?
+ if (m_eh_frame->GetAddressRange (addr, range))
+ {
+ FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range));
+ m_unwinds.push_back (unw);
+ std::sort (m_unwinds.begin(), m_unwinds.end());
+ return unw;
+ // FIXME we should create a syntheic Symbol based on the address range with a synthesized symbol name
+ }
+ }
+ return no_unwind_found;
+}
+
+DWARFCallFrameInfo *
+UnwindTable::GetEHFrameInfo ()
+{
+ initialize();
+ return m_eh_frame;
+}
OpenPOWER on IntegriCloud