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_eh_frame (NULL), 37 m_assembly_profiler (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 ConstString str; 62 m_object_file.GetTargetTriple (str); 63 arch.SetArchFromTargetTriple (str.GetCString()); 64 m_assembly_profiler = UnwindAssemblyProfiler::FindPlugin (arch); 65 66 m_initialized = true; 67 } 68 69 UnwindTable::~UnwindTable () 70 { 71 if (m_eh_frame) 72 delete m_eh_frame; 73 } 74 75 FuncUnwindersSP 76 UnwindTable::GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc) 77 { 78 FuncUnwindersSP no_unwind_found; 79 80 Initialize(); 81 82 // There is an UnwindTable per object file, so we can safely use file handles 83 addr_t file_addr = addr.GetFileAddress(); 84 iterator end = m_unwinds.end (); 85 iterator insert_pos = end; 86 if (!m_unwinds.empty()) 87 { 88 insert_pos = m_unwinds.lower_bound (file_addr); 89 iterator pos = insert_pos; 90 if ((pos == m_unwinds.end ()) || (pos != m_unwinds.begin() && pos->second->GetFunctionStartAddress() != addr)) 91 --pos; 92 93 if (pos->second->ContainsAddress (addr)) 94 return pos->second; 95 } 96 97 AddressRange range; 98 if (!sc.GetAddressRange(eSymbolContextFunction | eSymbolContextSymbol, range) || !range.GetBaseAddress().IsValid()) 99 { 100 // Does the eh_frame unwind info has a function bounds for this addr? 101 if (m_eh_frame == NULL || !m_eh_frame->GetAddressRange (addr, range)) 102 { 103 return no_unwind_found; 104 } 105 } 106 107 FuncUnwindersSP func_unwinder_sp(new FuncUnwinders(*this, m_assembly_profiler, range)); 108 m_unwinds.insert (insert_pos, std::make_pair(range.GetBaseAddress().GetFileAddress(), func_unwinder_sp)); 109 // StreamFile s(stdout); 110 // Dump (s); 111 return func_unwinder_sp; 112 } 113 114 void 115 UnwindTable::Dump (Stream &s) 116 { 117 s.Printf("UnwindTable for %s/%s:\n", m_object_file.GetFileSpec().GetDirectory().GetCString(), m_object_file.GetFileSpec().GetFilename().GetCString()); 118 const_iterator begin = m_unwinds.begin(); 119 const_iterator end = m_unwinds.end(); 120 for (const_iterator pos = begin; pos != end; ++pos) 121 { 122 s.Printf ("[%zu] 0x%16.16llx\n", std::distance (begin, pos), pos->first); 123 } 124 s.EOL(); 125 } 126 127 DWARFCallFrameInfo * 128 UnwindTable::GetEHFrameInfo () 129 { 130 Initialize(); 131 return m_eh_frame; 132 } 133