Files
clang-p2996/lldb/source/Symbol/UnwindTable.cpp
Jason Molenda a18f7071c2 A messy bit of cleanup: Move towards more descriptive names
for eh_frame and stabs register numberings.  This is not
complete but it's a step in the right direction.  It's almost
entirely mechanical.

lldb informally uses "gcc register numbering" to mean eh_frame.
Why?  Probably because there's a notorious bug with gcc on i386
darwin where the register numbers in eh_frame were incorrect.
In all other cases, eh_frame register numbering is identical to
dwarf.

lldb informally uses "gdb register numbering" to mean stabs.
There are no official definitions of stabs register numbers
for different architectures, so the implementations of gdb
and gcc are the de facto reference source.

There were some incorrect uses of these register number types
in lldb already.  I fixed the ones that I saw as I made
this change.

This commit changes all references to "gcc" and "gdb" register
numbers in lldb to "eh_frame" and "stabs" to make it clear 
what is actually being represented.

lldb cannot parse the stabs debug format, and given that no
one is using stabs any more, it is unlikely that it ever will.
A more comprehensive cleanup would remove the stabs register
numbers altogether - it's unnecessary cruft / complication to
all of our register structures.

In ProcessGDBRemote, when we get register definitions from
the gdb-remote stub, we expect to see "gcc:" (qRegisterInfo)
or "gcc_regnum" (qXfer:features:read: packet to get xml payload).
This patch changes ProcessGDBRemote to also accept "ehframe:"
and "ehframe_regnum" from these remotes.

I did not change GDBRemoteCommunicationServerLLGS or debugserver
to send these new packets.  I don't know what kind of interoperability
constraints we might be working under.  At some point in the future
we should transition to using the more descriptive names.

Throughout lldb we're still using enum names like "gcc_r0" and "gdb_r0",
for eh_frame and stabs register numberings.  These should be cleaned
up eventually too.

The sources link cleanly on macosx native with xcode build.  I
don't think we'll see problems on other platforms but please let
me know if I broke anyone.

llvm-svn: 245141
2015-08-15 01:21:01 +00:00

176 lines
5.0 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/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/Symbol/CompactUnwindInfo.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_mutex (),
m_eh_frame (nullptr),
m_compact_unwind (nullptr)
{
}
// 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;
Mutex::Locker locker(m_mutex);
if (m_initialized) // check again once we've acquired the lock
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, eRegisterKindEHFrame, true);
}
sect = sl->FindSectionByType (eSectionTypeCompactUnwind, true);
if (sect.get())
{
m_compact_unwind = new CompactUnwindInfo(m_object_file, sect);
}
}
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();
Mutex::Locker locker(m_mutex);
// There is an UnwindTable per object file, so we can safely use file handles
addr_t file_addr = addr.GetFileAddress();
iterator end = m_unwinds.end ();
iterator insert_pos = end;
if (!m_unwinds.empty())
{
insert_pos = m_unwinds.lower_bound (file_addr);
iterator pos = insert_pos;
if ((pos == m_unwinds.end ()) || (pos != m_unwinds.begin() && pos->second->GetFunctionStartAddress() != addr))
--pos;
if (pos->second->ContainsAddress (addr))
return pos->second;
}
AddressRange range;
if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
{
// Does the eh_frame unwind info has a function bounds for this addr?
if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
{
return no_unwind_found;
}
}
FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, range));
m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp));
// StreamFile s(stdout, false);
// Dump (s);
return func_unwinder_sp;
}
// Ignore any existing FuncUnwinders for this function, create a new one and don't add it to the
// UnwindTable. This is intended for use by target modules show-unwind where we want to create
// new UnwindPlans, not re-use existing ones.
FuncUnwindersSP
UnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
{
FuncUnwindersSP no_unwind_found;
Initialize();
AddressRange range;
if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
{
// Does the eh_frame unwind info has a function bounds for this addr?
if (m_eh_frame == nullptr || !m_eh_frame->GetAddressRange (addr, range))
{
return no_unwind_found;
}
}
FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, range));
return func_unwinder_sp;
}
void
UnwindTable::Dump (Stream &s)
{
Mutex::Locker locker(m_mutex);
s.Printf("UnwindTable for '%s':\n", m_object_file.GetFileSpec().GetPath().c_str());
const_iterator begin = m_unwinds.begin();
const_iterator end = m_unwinds.end();
for (const_iterator pos = begin; pos != end; ++pos)
{
s.Printf ("[%u] 0x%16.16" PRIx64 "\n", (unsigned)std::distance (begin, pos), pos->first);
}
s.EOL();
}
DWARFCallFrameInfo *
UnwindTable::GetEHFrameInfo ()
{
Initialize();
return m_eh_frame;
}
CompactUnwindInfo *
UnwindTable::GetCompactUnwindInfo ()
{
Initialize();
return m_compact_unwind;
}
bool
UnwindTable::GetArchitecture (lldb_private::ArchSpec &arch)
{
return m_object_file.GetArchitecture (arch);
}