llvm-project/lldb/source/Symbol/UnwindTable.cpp

134 lines
3.8 KiB
C++

//===-- 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/UnwindTable.h"
#include <stdio.h>
#include "lldb/lldb-forward.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Section.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/FuncUnwinders.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
#include "lldb/Utility/UnwindAssemblyProfiler.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;
}