]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfo.cpp
Merge clang 7.0.1 and several follow-up changes
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / lldb / source / Plugins / SymbolFile / DWARF / DWARFDebugInfo.cpp
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
28 using namespace lldb;
29 using namespace lldb_private;
30 using namespace std;
31
32 //----------------------------------------------------------------------
33 // Constructor
34 //----------------------------------------------------------------------
35 DWARFDebugInfo::DWARFDebugInfo()
36     : m_dwarf2Data(NULL), m_compile_units(), m_cu_aranges_ap() {}
37
38 //----------------------------------------------------------------------
39 // SetDwarfData
40 //----------------------------------------------------------------------
41 void DWARFDebugInfo::SetDwarfData(SymbolFileDWARF *dwarf2Data) {
42   m_dwarf2Data = dwarf2Data;
43   m_compile_units.clear();
44 }
45
46 DWARFDebugAranges &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
96 void 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
112 size_t DWARFDebugInfo::GetNumCompileUnits() {
113   ParseCompileUnitHeadersIfNeeded();
114   return m_compile_units.size();
115 }
116
117 DWARFUnit *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
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;
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
137 bool DWARFDebugInfo::OffsetLessThanCompileUnitOffset(
138     dw_offset_t offset, const DWARFUnitSP &cu_sp) {
139   return offset < cu_sp->GetOffset();
140 }
141
142 DWARFUnit *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
175 DWARFUnit *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
182 DWARFUnit *
183 DWARFDebugInfo::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
208 DWARFDIE
209 DWARFDebugInfo::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 //----------------------------------------------------------------------
221 DWARFDIE
222 DWARFDebugInfo::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