Home | History | Annotate | Download | only in Symbol
      1 //===-- UnwindTable.cpp -----------------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 
     10 #include "lldb/Symbol/UnwindTable.h"
     11 
     12 #include <stdio.h>
     13 
     14 #include "lldb/Core/Module.h"
     15 #include "lldb/Core/Section.h"
     16 #include "lldb/Symbol/ObjectFile.h"
     17 #include "lldb/Symbol/FuncUnwinders.h"
     18 #include "lldb/Symbol/SymbolContext.h"
     19 #include "lldb/Symbol/DWARFCallFrameInfo.h"
     20 #include "lldb/Target/UnwindAssembly.h"
     21 
     22 // There is one UnwindTable object per ObjectFile.
     23 // It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile.
     24 // Each Unwind object has multiple UnwindPlans for different scenarios.
     25 
     26 using namespace lldb;
     27 using namespace lldb_private;
     28 
     29 UnwindTable::UnwindTable (ObjectFile& objfile) :
     30     m_object_file (objfile),
     31     m_unwinds (),
     32     m_initialized (false),
     33     m_assembly_profiler (NULL),
     34     m_eh_frame (NULL)
     35 {
     36 }
     37 
     38 // We can't do some of this initialization when the ObjectFile is running its ctor; delay doing it
     39 // until needed for something.
     40 
     41 void
     42 UnwindTable::Initialize ()
     43 {
     44     if (m_initialized)
     45         return;
     46 
     47     SectionList* sl = m_object_file.GetSectionList ();
     48     if (sl)
     49     {
     50         SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true);
     51         if (sect.get())
     52         {
     53             m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true);
     54         }
     55     }
     56 
     57     ArchSpec arch;
     58     if (m_object_file.GetArchitecture (arch))
     59     {
     60         m_assembly_profiler = UnwindAssembly::FindPlugin (arch);
     61         m_initialized = true;
     62     }
     63 }
     64 
     65 UnwindTable::~UnwindTable ()
     66 {
     67     if (m_eh_frame)
     68         delete m_eh_frame;
     69 }
     70 
     71 FuncUnwindersSP
     72 UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
     73 {
     74     FuncUnwindersSP no_unwind_found;
     75 
     76     Initialize();
     77 
     78     // There is an UnwindTable per object file, so we can safely use file handles
     79     addr_t file_addr = addr.GetFileAddress();
     80     iterator end = m_unwinds.end ();
     81     iterator insert_pos = end;
     82     if (!m_unwinds.empty())
     83     {
     84         insert_pos = m_unwinds.lower_bound (file_addr);
     85         iterator pos = insert_pos;
     86         if ((pos == m_unwinds.end ()) || (pos != m_unwinds.begin() && pos->second->GetFunctionStartAddress() != addr))
     87             --pos;
     88 
     89         if (pos->second->ContainsAddress (addr))
     90             return pos->second;
     91     }
     92 
     93     AddressRange range;
     94     if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
     95     {
     96         // Does the eh_frame unwind info has a function bounds for this addr?
     97         if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range))
     98         {
     99             return no_unwind_found;
    100         }
    101     }
    102 
    103     FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range));
    104     m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp));
    105 //    StreamFile s(stdout);
    106 //    Dump (s);
    107     return func_unwinder_sp;
    108 }
    109 
    110 // Ignore any existing FuncUnwinders for this function, create a new one and don't add it to the
    111 // UnwindTable.  This is intended for use by target modules show-unwind where we want to create
    112 // new UnwindPlans, not re-use existing ones.
    113 
    114 FuncUnwindersSP
    115 UnwindTable::GetUncachedFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc)
    116 {
    117     FuncUnwindersSP no_unwind_found;
    118     Initialize();
    119 
    120     AddressRange range;
    121     if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, 0, false, range) || !range.GetBaseAddress().IsValid())
    122     {
    123         // Does the eh_frame unwind info has a function bounds for this addr?
    124         if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range))
    125         {
    126             return no_unwind_found;
    127         }
    128     }
    129 
    130     FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range));
    131     return func_unwinder_sp;
    132 }
    133 
    134 
    135 void
    136 UnwindTable::Dump (Stream &s)
    137 {
    138     s.Printf("UnwindTable for '%s':\n", m_object_file.GetFileSpec().GetPath().c_str());
    139     const_iterator begin = m_unwinds.begin();
    140     const_iterator end = m_unwinds.end();
    141     for (const_iterator pos = begin; pos != end; ++pos)
    142     {
    143         s.Printf ("[%u] 0x%16.16" PRIx64 "\n", (unsigned)std::distance (begin, pos), pos->first);
    144     }
    145     s.EOL();
    146 }
    147 
    148 DWARFCallFrameInfo *
    149 UnwindTable::GetEHFrameInfo ()
    150 {
    151     Initialize();
    152     return m_eh_frame;
    153 }
    154