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/lldb-forward.h" 15 16 #include "lldb/Core/Module.h" 17 #include "lldb/Core/Section.h" 18 //#include "lldb/Core/StreamFile.h" 19 #include "lldb/Symbol/ObjectFile.h" 20 #include "lldb/Symbol/FuncUnwinders.h" 21 #include "lldb/Symbol/SymbolContext.h" 22 #include "lldb/Symbol/DWARFCallFrameInfo.h" 23 #include "lldb/Utility/UnwindAssemblyProfiler.h" 24 25 // There is one UnwindTable object per ObjectFile. 26 // It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile. 27 // Each Unwind object has multiple UnwindPlans for different scenarios. 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 UnwindTable::UnwindTable (ObjectFile& objfile) : 33 m_object_file (objfile), 34 m_unwinds (), 35 m_initialized (false), 36 m_assembly_profiler (NULL), 37 m_eh_frame (NULL) 38 { 39 } 40 41 // We can't do some of this initialization when the ObjectFile is running its ctor; delay doing it 42 // until needed for something. 43 44 void 45 UnwindTable::Initialize () 46 { 47 if (m_initialized) 48 return; 49 50 SectionList* sl = m_object_file.GetSectionList (); 51 if (sl) 52 { 53 SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true); 54 if (sect.get()) 55 { 56 m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true); 57 } 58 } 59 60 ArchSpec arch; 61 if (m_object_file.GetArchitecture (arch)) 62 { 63 m_assembly_profiler = UnwindAssemblyProfiler::FindPlugin (arch); 64 m_initialized = true; 65 } 66 } 67 68 UnwindTable::~UnwindTable () 69 { 70 if (m_eh_frame) 71 delete m_eh_frame; 72 } 73 74 FuncUnwindersSP 75 UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc) 76 { 77 FuncUnwindersSP no_unwind_found; 78 79 Initialize(); 80 81 // There is an UnwindTable per object file, so we can safely use file handles 82 addr_t file_addr = addr.GetFileAddress(); 83 iterator end = m_unwinds.end (); 84 iterator insert_pos = end; 85 if (!m_unwinds.empty()) 86 { 87 insert_pos = m_unwinds.lower_bound (file_addr); 88 iterator pos = insert_pos; 89 if ((pos == m_unwinds.end ()) || (pos != m_unwinds.begin() && pos->second->GetFunctionStartAddress() != addr)) 90 --pos; 91 92 if (pos->second->ContainsAddress (addr)) 93 return pos->second; 94 } 95 96 AddressRange range; 97 if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range) || !range.GetBaseAddress().IsValid()) 98 { 99 // Does the eh_frame unwind info has a function bounds for this addr? 100 if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range)) 101 { 102 return no_unwind_found; 103 } 104 } 105 106 FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range)); 107 m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp)); 108 // StreamFile s(stdout); 109 // Dump (s); 110 return func_unwinder_sp; 111 } 112 113 void 114 UnwindTable::Dump (Stream &s) 115 { 116 s.Printf("UnwindTable for %s/%s:\n", m_object_file.GetFileSpec().GetDirectory().GetCString(), m_object_file.GetFileSpec().GetFilename().GetCString()); 117 const_iterator begin = m_unwinds.begin(); 118 const_iterator end = m_unwinds.end(); 119 for (const_iterator pos = begin; pos != end; ++pos) 120 { 121 s.Printf ("[%zu] 0x%16.16llx\n", std::distance (begin, pos), pos->first); 122 } 123 s.EOL(); 124 } 125 126 DWARFCallFrameInfo * 127 UnwindTable::GetEHFrameInfo () 128 { 129 Initialize(); 130 return m_eh_frame; 131 } 132