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/Symbol/ObjectFile.h" 19 #include "lldb/Symbol/FuncUnwinders.h" 20 #include "lldb/Symbol/SymbolContext.h" 21 #include "lldb/Symbol/DWARFCallFrameInfo.h" 22 #include "lldb/Utility/UnwindAssemblyProfiler.h" 23 24 // There is one UnwindTable object per ObjectFile. 25 // It contains a list of Unwind objects -- one per function, populated lazily -- for the ObjectFile. 26 // Each Unwind object has multiple UnwindPlans for different scenarios. 27 28 using namespace lldb; 29 using namespace lldb_private; 30 31 UnwindTable::UnwindTable (ObjectFile& objfile) : m_object_file(objfile), 32 m_unwinds(), 33 m_initialized(false), 34 m_eh_frame(NULL), 35 m_assembly_profiler(NULL) 36 { 37 } 38 39 // We can't do some of this initialization when the ObjectFile is running its ctor; delay doing it 40 // until needed for something. 41 42 void 43 UnwindTable::initialize () 44 { 45 if (m_initialized) 46 return; 47 48 SectionList* sl = m_object_file.GetSectionList (); 49 if (sl) 50 { 51 SectionSP sect = sl->FindSectionByType (eSectionTypeEHFrame, true); 52 if (sect.get()) 53 { 54 m_eh_frame = new DWARFCallFrameInfo(m_object_file, sect, eRegisterKindGCC, true); 55 } 56 } 57 58 ArchSpec arch; 59 ConstString str; 60 m_object_file.GetTargetTriple (str); 61 arch.SetArchFromTargetTriple (str.GetCString()); 62 m_assembly_profiler = UnwindAssemblyProfiler::FindPlugin (arch); 63 64 m_initialized = true; 65 } 66 67 UnwindTable::~UnwindTable () 68 { 69 if (m_eh_frame) 70 delete m_eh_frame; 71 } 72 73 FuncUnwindersSP 74 UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc) 75 { 76 FuncUnwindersSP no_unwind_found; 77 78 initialize(); 79 80 // Create a FuncUnwinders object for the binary search below 81 AddressRange search_range(addr, 1); 82 FuncUnwindersSP search_unwind(new FuncUnwinders (*this, NULL, search_range)); 83 84 const_iterator idx; 85 idx = std::lower_bound (m_unwinds.begin(), m_unwinds.end(), search_unwind); 86 87 bool found_match = true; 88 if (m_unwinds.size() == 0) 89 { 90 found_match = false; 91 } 92 else if (idx == m_unwinds.end()) 93 { 94 --idx; 95 } 96 if (idx != m_unwinds.begin() && (*idx)->GetFunctionStartAddress().GetOffset() != addr.GetOffset()) 97 { 98 --idx; 99 } 100 if (found_match && (*idx)->ContainsAddress (addr)) 101 { 102 return *idx; 103 } 104 105 AddressRange range; 106 if (sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range)) 107 { 108 FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range)); 109 m_unwinds.push_back (unw); 110 std::sort (m_unwinds.begin(), m_unwinds.end()); 111 return unw; 112 } 113 else 114 { 115 // Does the eh_frame unwind info has a function bounds defined for this addr? 116 if (m_eh_frame->GetAddressRange (addr, range)) 117 { 118 FuncUnwindersSP unw(new FuncUnwinders(*this, m_assembly_profiler, range)); 119 m_unwinds.push_back (unw); 120 std::sort (m_unwinds.begin(), m_unwinds.end()); 121 return unw; 122 // FIXME we should create a syntheic Symbol based on the address range with a synthesized symbol name 123 } 124 } 125 return no_unwind_found; 126 } 127 128 DWARFCallFrameInfo * 129 UnwindTable::GetEHFrameInfo () 130 { 131 initialize(); 132 return m_eh_frame; 133 } 134