DWARFDebugInfo.cpp revision 341825
1//===-- DWARFDebugInfo.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 "SymbolFileDWARF.h" 11 12#include <algorithm> 13#include <set> 14 15#include "lldb/Host/PosixApi.h" 16#include "lldb/Symbol/ObjectFile.h" 17#include "lldb/Utility/RegularExpression.h" 18#include "lldb/Utility/Stream.h" 19 20#include "DWARFCompileUnit.h" 21#include "DWARFDebugAranges.h" 22#include "DWARFDebugAranges.h" 23#include "DWARFDebugInfo.h" 24#include "DWARFDebugInfoEntry.h" 25#include "DWARFFormValue.h" 26#include "LogChannelDWARF.h" 27 28using namespace lldb; 29using namespace lldb_private; 30using namespace std; 31 32//---------------------------------------------------------------------- 33// Constructor 34//---------------------------------------------------------------------- 35DWARFDebugInfo::DWARFDebugInfo() 36 : m_dwarf2Data(NULL), m_compile_units(), m_cu_aranges_ap() {} 37 38//---------------------------------------------------------------------- 39// SetDwarfData 40//---------------------------------------------------------------------- 41void DWARFDebugInfo::SetDwarfData(SymbolFileDWARF *dwarf2Data) { 42 m_dwarf2Data = dwarf2Data; 43 m_compile_units.clear(); 44} 45 46DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() { 47 if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data) { 48 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 49 50 m_cu_aranges_ap.reset(new DWARFDebugAranges()); 51 const DWARFDataExtractor &debug_aranges_data = 52 m_dwarf2Data->get_debug_aranges_data(); 53 if (debug_aranges_data.GetByteSize() > 0) { 54 if (log) 55 log->Printf( 56 "DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from " 57 ".debug_aranges", 58 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str()); 59 m_cu_aranges_ap->Extract(debug_aranges_data); 60 } 61 62 // Make a list of all CUs represented by the arange data in the file. 63 std::set<dw_offset_t> cus_with_data; 64 for (size_t n = 0; n < m_cu_aranges_ap.get()->GetNumRanges(); n++) { 65 dw_offset_t offset = m_cu_aranges_ap.get()->OffsetAtIndex(n); 66 if (offset != DW_INVALID_OFFSET) 67 cus_with_data.insert(offset); 68 } 69 70 // Manually build arange data for everything that wasn't in the 71 // .debug_aranges table. 72 bool printed = false; 73 const size_t num_compile_units = GetNumCompileUnits(); 74 for (size_t idx = 0; idx < num_compile_units; ++idx) { 75 DWARFUnit *cu = GetCompileUnitAtIndex(idx); 76 77 dw_offset_t offset = cu->GetOffset(); 78 if (cus_with_data.find(offset) == cus_with_data.end()) { 79 if (log) { 80 if (!printed) 81 log->Printf( 82 "DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing", 83 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str()); 84 printed = true; 85 } 86 cu->BuildAddressRangeTable(m_dwarf2Data, m_cu_aranges_ap.get()); 87 } 88 } 89 90 const bool minimize = true; 91 m_cu_aranges_ap->Sort(minimize); 92 } 93 return *m_cu_aranges_ap.get(); 94} 95 96void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() { 97 if (m_compile_units.empty()) { 98 if (m_dwarf2Data != NULL) { 99 lldb::offset_t offset = 0; 100 DWARFUnitSP cu_sp; 101 const auto &debug_info_data = m_dwarf2Data->get_debug_info_data(); 102 while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data, 103 &offset))) { 104 m_compile_units.push_back(cu_sp); 105 106 offset = cu_sp->GetNextCompileUnitOffset(); 107 } 108 } 109 } 110} 111 112size_t DWARFDebugInfo::GetNumCompileUnits() { 113 ParseCompileUnitHeadersIfNeeded(); 114 return m_compile_units.size(); 115} 116 117DWARFUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) { 118 DWARFUnit *cu = NULL; 119 if (idx < GetNumCompileUnits()) 120 cu = m_compile_units[idx].get(); 121 return cu; 122} 123 124bool DWARFDebugInfo::ContainsCompileUnit(const DWARFUnit *cu) const { 125 // Not a verify efficient function, but it is handy for use in assertions to 126 // make sure that a compile unit comes from a debug information file. 127 CompileUnitColl::const_iterator end_pos = m_compile_units.end(); 128 CompileUnitColl::const_iterator pos; 129 130 for (pos = m_compile_units.begin(); pos != end_pos; ++pos) { 131 if (pos->get() == cu) 132 return true; 133 } 134 return false; 135} 136 137bool DWARFDebugInfo::OffsetLessThanCompileUnitOffset( 138 dw_offset_t offset, const DWARFUnitSP &cu_sp) { 139 return offset < cu_sp->GetOffset(); 140} 141 142DWARFUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset, 143 uint32_t *idx_ptr) { 144 DWARFUnitSP cu_sp; 145 uint32_t cu_idx = DW_INVALID_INDEX; 146 if (cu_offset != DW_INVALID_OFFSET) { 147 ParseCompileUnitHeadersIfNeeded(); 148 149 // Watch out for single compile unit executable as they are pretty common 150 const size_t num_cus = m_compile_units.size(); 151 if (num_cus == 1) { 152 if (m_compile_units[0]->GetOffset() == cu_offset) { 153 cu_sp = m_compile_units[0]; 154 cu_idx = 0; 155 } 156 } else if (num_cus) { 157 CompileUnitColl::const_iterator end_pos = m_compile_units.end(); 158 CompileUnitColl::const_iterator begin_pos = m_compile_units.begin(); 159 CompileUnitColl::const_iterator pos = std::upper_bound( 160 begin_pos, end_pos, cu_offset, OffsetLessThanCompileUnitOffset); 161 if (pos != begin_pos) { 162 --pos; 163 if ((*pos)->GetOffset() == cu_offset) { 164 cu_sp = *pos; 165 cu_idx = std::distance(begin_pos, pos); 166 } 167 } 168 } 169 } 170 if (idx_ptr) 171 *idx_ptr = cu_idx; 172 return cu_sp.get(); 173} 174 175DWARFUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) { 176 if (die_ref.cu_offset == DW_INVALID_OFFSET) 177 return GetCompileUnitContainingDIEOffset(die_ref.die_offset); 178 else 179 return GetCompileUnit(die_ref.cu_offset); 180} 181 182DWARFUnit * 183DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) { 184 ParseCompileUnitHeadersIfNeeded(); 185 186 DWARFUnitSP cu_sp; 187 188 // Watch out for single compile unit executable as they are pretty common 189 const size_t num_cus = m_compile_units.size(); 190 if (num_cus == 1) { 191 if (m_compile_units[0]->ContainsDIEOffset(die_offset)) 192 return m_compile_units[0].get(); 193 } else if (num_cus) { 194 CompileUnitColl::const_iterator end_pos = m_compile_units.end(); 195 CompileUnitColl::const_iterator begin_pos = m_compile_units.begin(); 196 CompileUnitColl::const_iterator pos = std::upper_bound( 197 begin_pos, end_pos, die_offset, OffsetLessThanCompileUnitOffset); 198 if (pos != begin_pos) { 199 --pos; 200 if ((*pos)->ContainsDIEOffset(die_offset)) 201 return (*pos).get(); 202 } 203 } 204 205 return nullptr; 206} 207 208DWARFDIE 209DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) { 210 DWARFUnit *cu = GetCompileUnitContainingDIEOffset(die_offset); 211 if (cu) 212 return cu->GetDIE(die_offset); 213 return DWARFDIE(); 214} 215 216//---------------------------------------------------------------------- 217// GetDIE() 218// 219// Get the DIE (Debug Information Entry) with the specified offset. 220//---------------------------------------------------------------------- 221DWARFDIE 222DWARFDebugInfo::GetDIE(const DIERef &die_ref) { 223 DWARFUnit *cu = GetCompileUnit(die_ref); 224 if (cu) 225 return cu->GetDIE(die_ref.die_offset); 226 return DWARFDIE(); // Not found 227} 228 229