forked from OSchip/llvm-project
134 lines
3.8 KiB
C++
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;
|
|
}
|