197eecb1834431b39d4d58257f8ccfdea1db7f1deGreg Clayton//===-- UnwindTable.cpp -----------------------------------------*- C++ -*-===//
23a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//
33a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//                     The LLVM Compiler Infrastructure
43a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//
53a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// This file is distributed under the University of Illinois Open Source
63a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// License. See LICENSE.TXT for details.
73a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//
83a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda//===----------------------------------------------------------------------===//
93a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
10412440aa3a110e4068ee99729f7883c828fb3dceGreg Clayton#include "lldb/Symbol/UnwindTable.h"
113a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
12412440aa3a110e4068ee99729f7883c828fb3dceGreg Clayton#include <stdio.h>
13412440aa3a110e4068ee99729f7883c828fb3dceGreg Clayton
14412440aa3a110e4068ee99729f7883c828fb3dceGreg Clayton#include "lldb/Core/Module.h"
15412440aa3a110e4068ee99729f7883c828fb3dceGreg Clayton#include "lldb/Core/Section.h"
16412440aa3a110e4068ee99729f7883c828fb3dceGreg Clayton#include "lldb/Symbol/ObjectFile.h"
173a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Symbol/FuncUnwinders.h"
183a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Symbol/SymbolContext.h"
193a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda#include "lldb/Symbol/DWARFCallFrameInfo.h"
208badcb2503ed2e2884a48f66099c1d48494817f4Greg Clayton#include "lldb/Target/UnwindAssembly.h"
213a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
223a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// There is one UnwindTable object per ObjectFile.
233a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile.
243a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// Each Unwind object has multiple UnwindPlans for different scenarios.
253a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
263a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendausing namespace lldb;
273a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendausing namespace lldb_private;
283a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
29e2f90647b93b0f44c0222da8d995dfe267499f9cGreg ClaytonUnwindTable::UnwindTable (ObjectFile& objfile) :
30e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    m_object_file (objfile),
31e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    m_unwinds (),
32e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    m_initialized (false),
33dbeb3e1e038a75f00fd565203839020e1d00a7c6Stephen Wilson    m_assembly_profiler (NULL),
34dbeb3e1e038a75f00fd565203839020e1d00a7c6Stephen Wilson    m_eh_frame (NULL)
353a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
363a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
373a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
383a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// We can't do some of this initialization when the ObjectFile is running its ctor; delay doing it
393a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda// until needed for something.
403a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
413a4ea24572fad1e22525f8efb718d49d41e30398Jason Molendavoid
42e2f90647b93b0f44c0222da8d995dfe267499f9cGreg ClaytonUnwindTable::Initialize ()
433a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
443a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_initialized)
453a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        return;
463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    SectionList* sl = m_object_file.GetSectionList ();
483a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (sl)
493a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
503a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true);
513a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        if (sect.get())
523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda            m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true);
543a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
553a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
563a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
573a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    ArchSpec arch;
58395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton    if (m_object_file.GetArchitecture (arch))
59395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton    {
608badcb2503ed2e2884a48f66099c1d48494817f4Greg Clayton        m_assembly_profiler = UnwindAssembly::FindPlugin (arch);
61395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton        m_initialized = true;
62395fc33dc4b06c048ed35047ec461bc092ef2df3Greg Clayton    }
633a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
643a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
653a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindTable::~UnwindTable ()
663a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
673a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    if (m_eh_frame)
683a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        delete m_eh_frame;
693a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
703a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
713a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaFuncUnwindersSP
723a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
733a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
743a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    FuncUnwindersSP no_unwind_found;
753a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
76e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    Initialize();
773a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
78e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    // There is an UnwindTable per object file, so we can safely use file handles
79e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    addr_t file_addr = addr.GetFileAddress();
80e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    iterator end = m_unwinds.end ();
81e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    iterator insert_pos = end;
82e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    if (!m_unwinds.empty())
833a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
84e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton        insert_pos = m_unwinds.lower_bound (file_addr);
85e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton        iterator pos = insert_pos;
86e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton        if ((pos == m_unwinds.end ()) || (pos != m_unwinds.begin() && pos->second->GetFunctionStartAddress() != addr))
87e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton            --pos;
88e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton
89e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton        if (pos->second->ContainsAddress (addr))
90e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton            return pos->second;
913a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
923a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
933a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    AddressRange range;
94ff44ab42e9f5d8e4d550e11d1b69413e0bc75b71Greg Clayton    if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
953a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    {
96800d11d87769e1a7083f7a5545613625396deb3eJason Molenda        // Does the eh_frame unwind info has a function bounds for this addr?
97d6ef16aab825a1319179d1445f35538f535e9bf1Jason Molenda        if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range))
983a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        {
99800d11d87769e1a7083f7a5545613625396deb3eJason Molenda            return no_unwind_found;
1003a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda        }
1013a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    }
102800d11d87769e1a7083f7a5545613625396deb3eJason Molenda
103e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range));
104e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp));
105e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton//    StreamFile s(stdout);
106e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton//    Dump (s);
107e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    return func_unwinder_sp;
108e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton}
109e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton
1105b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda// Ignore any existing FuncUnwinders for this function, create a new one and don't add it to the
1115b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda// UnwindTable.  This is intended for use by target modules show-unwind where we want to create
1125b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda// new UnwindPlans, not re-use existing ones.
1135b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda
1145b0afcceea3807fa8f518e0138f0a8043dfc3315Jason MolendaFuncUnwindersSP
1155b0afcceea3807fa8f518e0138f0a8043dfc3315Jason MolendaUnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
1165b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda{
1175b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda    FuncUnwindersSP no_unwind_found;
1185b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda    Initialize();
1195b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda
1205b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda    AddressRange range;
1215b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda    if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
1225b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda    {
1235b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda        // Does the eh_frame unwind info has a function bounds for this addr?
1245b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda        if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range))
1255b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda        {
1265b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda            return no_unwind_found;
1275b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda        }
1285b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda    }
1295b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda
1305b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda    FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range));
1315b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda    return func_unwinder_sp;
1325b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda}
1335b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda
1345b0afcceea3807fa8f518e0138f0a8043dfc3315Jason Molenda
135e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Claytonvoid
136e2f90647b93b0f44c0222da8d995dfe267499f9cGreg ClaytonUnwindTable::Dump (Stream &s)
137e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton{
13897a19b21dacd9063bb5475812df7781777262198Greg Clayton    s.Printf("UnwindTable for '%s':\n", m_object_file.GetFileSpec().GetPath().c_str());
139e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    const_iterator begin = m_unwinds.begin();
140e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    const_iterator end = m_unwinds.end();
141e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    for (const_iterator pos = begin; pos != end; ++pos)
142e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    {
1435f35a4be95aed0e5b2cb36f7d785bcbfc67284aeDaniel Malea        s.Printf ("[%u] 0x%16.16" PRIx64 "\n", (unsigned)std::distance (begin, pos), pos->first);
144e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    }
145e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    s.EOL();
1463a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
1473a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda
1483a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaDWARFCallFrameInfo *
1493a4ea24572fad1e22525f8efb718d49d41e30398Jason MolendaUnwindTable::GetEHFrameInfo ()
1503a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda{
151e2f90647b93b0f44c0222da8d995dfe267499f9cGreg Clayton    Initialize();
1523a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda    return m_eh_frame;
1533a4ea24572fad1e22525f8efb718d49d41e30398Jason Molenda}
154