1 //===-- DWARFDebugInfo.cpp --------------------------------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "SymbolFileDWARF.h"
15 #include "lldb/Host/PosixApi.h"
16 #include "lldb/Symbol/ObjectFile.h"
17 #include "lldb/Utility/RegularExpression.h"
18 #include "lldb/Utility/Stream.h"
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"
29 using namespace lldb_private;
32 //----------------------------------------------------------------------
34 //----------------------------------------------------------------------
35 DWARFDebugInfo::DWARFDebugInfo()
36 : m_dwarf2Data(NULL), m_compile_units(), m_cu_aranges_ap() {}
38 //----------------------------------------------------------------------
40 //----------------------------------------------------------------------
41 void DWARFDebugInfo::SetDwarfData(SymbolFileDWARF *dwarf2Data) {
42 m_dwarf2Data = dwarf2Data;
43 m_compile_units.clear();
46 DWARFDebugAranges &DWARFDebugInfo::GetCompileUnitAranges() {
47 if (m_cu_aranges_ap.get() == NULL && m_dwarf2Data) {
48 Log *log(LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES));
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) {
56 "DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" from "
58 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
59 m_cu_aranges_ap->Extract(debug_aranges_data);
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);
70 // Manually build arange data for everything that wasn't in the
71 // .debug_aranges table.
73 const size_t num_compile_units = GetNumCompileUnits();
74 for (size_t idx = 0; idx < num_compile_units; ++idx) {
75 DWARFUnit *cu = GetCompileUnitAtIndex(idx);
77 dw_offset_t offset = cu->GetOffset();
78 if (cus_with_data.find(offset) == cus_with_data.end()) {
82 "DWARFDebugInfo::GetCompileUnitAranges() for \"%s\" by parsing",
83 m_dwarf2Data->GetObjectFile()->GetFileSpec().GetPath().c_str());
86 cu->BuildAddressRangeTable(m_dwarf2Data, m_cu_aranges_ap.get());
90 const bool minimize = true;
91 m_cu_aranges_ap->Sort(minimize);
93 return *m_cu_aranges_ap.get();
96 void DWARFDebugInfo::ParseCompileUnitHeadersIfNeeded() {
97 if (m_compile_units.empty()) {
98 if (m_dwarf2Data != NULL) {
99 lldb::offset_t offset = 0;
101 const auto &debug_info_data = m_dwarf2Data->get_debug_info_data();
102 while ((cu_sp = DWARFCompileUnit::Extract(m_dwarf2Data, debug_info_data,
104 m_compile_units.push_back(cu_sp);
106 offset = cu_sp->GetNextCompileUnitOffset();
112 size_t DWARFDebugInfo::GetNumCompileUnits() {
113 ParseCompileUnitHeadersIfNeeded();
114 return m_compile_units.size();
117 DWARFUnit *DWARFDebugInfo::GetCompileUnitAtIndex(uint32_t idx) {
118 DWARFUnit *cu = NULL;
119 if (idx < GetNumCompileUnits())
120 cu = m_compile_units[idx].get();
124 bool 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;
130 for (pos = m_compile_units.begin(); pos != end_pos; ++pos) {
131 if (pos->get() == cu)
137 bool DWARFDebugInfo::OffsetLessThanCompileUnitOffset(
138 dw_offset_t offset, const DWARFUnitSP &cu_sp) {
139 return offset < cu_sp->GetOffset();
142 DWARFUnit *DWARFDebugInfo::GetCompileUnit(dw_offset_t cu_offset,
145 uint32_t cu_idx = DW_INVALID_INDEX;
146 if (cu_offset != DW_INVALID_OFFSET) {
147 ParseCompileUnitHeadersIfNeeded();
149 // Watch out for single compile unit executable as they are pretty common
150 const size_t num_cus = m_compile_units.size();
152 if (m_compile_units[0]->GetOffset() == cu_offset) {
153 cu_sp = m_compile_units[0];
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) {
163 if ((*pos)->GetOffset() == cu_offset) {
165 cu_idx = std::distance(begin_pos, pos);
175 DWARFUnit *DWARFDebugInfo::GetCompileUnit(const DIERef &die_ref) {
176 if (die_ref.cu_offset == DW_INVALID_OFFSET)
177 return GetCompileUnitContainingDIEOffset(die_ref.die_offset);
179 return GetCompileUnit(die_ref.cu_offset);
183 DWARFDebugInfo::GetCompileUnitContainingDIEOffset(dw_offset_t die_offset) {
184 ParseCompileUnitHeadersIfNeeded();
188 // Watch out for single compile unit executable as they are pretty common
189 const size_t num_cus = m_compile_units.size();
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) {
200 if ((*pos)->ContainsDIEOffset(die_offset))
209 DWARFDebugInfo::GetDIEForDIEOffset(dw_offset_t die_offset) {
210 DWARFUnit *cu = GetCompileUnitContainingDIEOffset(die_offset);
212 return cu->GetDIE(die_offset);
216 //----------------------------------------------------------------------
219 // Get the DIE (Debug Information Entry) with the specified offset.
220 //----------------------------------------------------------------------
222 DWARFDebugInfo::GetDIE(const DIERef &die_ref) {
223 DWARFUnit *cu = GetCompileUnit(die_ref);
225 return cu->GetDIE(die_ref.die_offset);
226 return DWARFDIE(); // Not found